Docker 初步学习如何使用 docker 和 docker-compose 部署项目

蔡瑞淳 for 君海游戏QA · 2019年04月09日 · 1981 次阅读

参考一些文章学习 docker 相关知识,稍微做下整理,若有问题,欢迎指正,具体参考文章附在最后。

一、docker

docker 概述

三大概念:镜像(Image)、容器(Container)、仓库(Repository)。

镜像类似面向对象程序设计中的类,容器类似根据类创建的一个实例,容器与容器之间是独立的,仓库是用于存储镜像,使得在任意一台机器上,可以从仓库拉取指定的镜像到本地进行构建。项目开发者可以利用 docker 这种特性来构建项目的镜像,供多个开发者和测试人员使用,在保证开发环境和测试环境一致的同时省去搭建环境等繁琐事务。

1、镜像
docker 镜像是一个特殊的文件系统,提供容器运行时所需的程序、库、资源、配置等文件和一些配置参数(如匿名卷、环境变量、用户等),不含任何动态数据,其内容在构建后不会被改变。

分层存储概念:
(1)镜像构建时会一层层构建,前一层是后一层的基础。每一层构建完便不再改变,后一层上的任何改变只发生在自己这一层。
(2)如删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像时,每一层尽量只包含该层需要的东西,任何额外的应在该层构建结束前清理掉。

2、容器
容器是镜像运行时的实体,容器内的进程是运行在一个隔离的环境里,使用时像是在一个独立于宿主的系统下操作。

容器中有 容器存储层,运行时用于读写,但按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入都应该使用 数据卷(Volume)或绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

3、仓库
docker registry 提供这样的服务,一个 Docker Registry 中可以包含多个仓库,每个仓库可以包含多个标签,每个标签对应一个镜像。

docker registry 提供公开和付费服务。公开服务是官方的 docker hub,用户可免费上传和下载。付费服务供用户管理私有镜像。

因为一些原因访问 docker hub 有时比较慢,可通过 加速器 进行加速。

docker 安装

1、环境:ubuntu16.04(64 位)

2、安装步骤(参照官网):
(1)安装 CA 证书,支持 https(前期准备)
$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
(2)添加官方软件源的 GPG 密钥
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
(3)验证密钥
$ sudo apt-key fingerprint 0EBFCD8
(4)添加稳定版本的 Docker CE API 镜像源
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
(5)安装 docker ce
$ sudo apt-get update
$ sudo apt-get install docker-ce
(6)启动 docker
systemctl enable docker / systemctl start docker
注意:只有 root 用户和 docker 组的用户才可以访问 docker
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
(7)测试 docker 是否安装成功
$ docker run hello-world

3、使用镜像加速器

在/etc/docker/daemon.json写入如下内容,并重启服务:
{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ]
}

docker 镜像构建

一般可通过 docker commit 或者 dockerfile 2 种方式进行镜像构建。

1、docker commit(不推荐)

举个例子,原文见https://yeasy.gitbooks.io/docker_practice/content/image/commit.html
(1)基于 nginx 镜像启动一个容器

docker run --name web -d -p 8000:80 nginx

(2)启动后通过http://127.0.0.1:8000nginx 首页可访问
(3)进入容器中进行修改,如修改 nginx 首页内容

docker exec -ti web bash 
echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
exit

(4)再次访问 nginx 首页,发现已更改
(5)通过 docker commit 将容器所有东西(原有镜像 + 存储层)保存下来成为镜像

docker commit web nginx:v1.1

容器也是多层存储,以上例子在原有基础镜像上做了一层修改(添加一个新文件),然后提交。

试想使用该镜像的用户操作了很多命令后用 docker commit 提交新镜像,而用户本身也记不清做过了哪些修改,后续维护困难。另外,期间的操作可能会引入其他无关内容进来,每一层下来都会增加一个新文件,慢慢累积就变成了十分臃肿的黑箱镜像,这个一点也不符合我们的初衷。

2、dockerfile 方式

镜像的定制过程其实是根据一条条命令在原有基础上去执行对应的操作,如果我们把这些操作清楚地写入一个脚本,按照脚本中的流程来构建镜像,那只要我们维护好这个脚本,便可使我们的镜像内容清晰且轻量。

(1)编写 dockerfile 文件

FROM debian:stretch
RUN buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

(2)在 Dockerfile 文件所在目录执行:

$ docker build -t nginx:v3 .

注意:后面的 “.” 表示当前目录

二、docker-compose

负责实现对 Docker 容器集群的快速编排。通过 dockerfile 可以很方便地定义一个单独的容器,但实际工作中,可能需要多个容器协作完成任务,比如 web 服务、数据库服务等。一个项目中可通过 docker-compose.yml 来定义一组相关联的容器。

1、安装
pip install docker-compose/apt install docker-compose
docker-compose --version

2、应用场景
一个 web 网站,包含 web 应用(flask)和缓存(redis)。

(1)编写 app.py

from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
    count = redis.incr('hits')
    return 'Hello World! 该页面已被访问 {} 次。\n'.format(count)
if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

(2)编写 dockerfile 文件

FROM python:3.6-alpine
ADD . /code
WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]

(3)编写 docker-compose.yml

version: '3'
services:
  web:
    build: .
    ports:
     - "5001:5000"
  redis:
    image: "redis:alpine"

(4)在 docker-compose 目录下启动容器:

docker-compose up -d

ps:以上内容主要参考网址:
1、https://yeasy.gitbooks.io/docker_practice/content/
2、https://docs.docker.com/install/linux/docker-ce/ubuntu/
3、https://blog.csdn.net/jay100500/article/details/76472939

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册