介绍

Dockerfile用于构建镜像,它可以让用户个性化定制Docker镜像,因为网上的基础镜像不能够满足我们各种各样的要求,而Docker Compose用来高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具,当我们做微服务的时候,有众多的服务,使用Docker Compose可以帮助我们统一管理运行这些服务的环境变量,和服务之间的依赖关系,启动顺序等等。

Dockerfile

介绍

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,这个脚本就是 Dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
Dockerfile一般包含下面几个部分:
基础镜像:以哪个镜像作为基础进行制作,用法是FROM 基础镜像名称
镜像操作命令:对基础镜像要进行的改造命令,比如安装新的软件,进行哪些特殊配置等,常见的是RUN 命令
容器启动命令:当基于该镜像的容器启动时需要执行哪些命令,常见的是CMD 命令或ENTRYPOINT

指令说明

FROM(指定基础镜像)

定制镜像,首先要以一个镜像为基础,在它的基础上进行定制。FROM指令用于指定基础镜像,且必须是第一条指令。
Docker Hub 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 nginxredismongomysqlhttpdphptomcat 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 nodeopenjdkpythonrubygolang 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。
如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如 ubuntudebiancentosfedoraalpine 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。
除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。
格式:FROM <镜像名:版本号>
示例:

  1. FROM java:8

这里指定基础镜像是java,版本号是8。

LABEL (添加元数据)

LABEL 指令用来给镜像以键值对的形式添加一些元数据(metadata)。
格式:LABEL = = =
示例:

  1. LABEL version="1.0" description="This is description"

VOLUME (定义匿名卷)

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
格式:

  • VOLUME [“<路径1>”, “<路径2>”…]
  • VOLUME <路径>

示例:

  1. VOLUME /tmp

这里的 /tmp目录就会在容器运行时自动挂载为匿名卷,任何向 /tmp中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。

COPY (复制)

复制本地主机中的文件到容器中 。目标路径不存在时,会自动创建。复制的路径可以使用通配符。
格式:

  • COPY [—chown=:] <源路径>… <目标路径>
  • COPY [—chown=:] [“<源路径1>”,… “<目标路径>”]

示例:

  1. COPY *.log /log/

该代码复制所有的.log文件到log/目录下。

ADD (更高级的复制)

ADD格式与COPY格式一致。和COPY不同的是,源路径可以是一个URL,那么它可以自动下载文件,或者是一个压缩包,可以自动解压缩到目标路径去,如果你不想解压的话,就不要使用ADD命令了。
格式:

  • ADD[—chown=:] <源路径>… <目标路径>
  • ADD[—chown=:] [“<源路径1>”,… “<目标路径>”]

示例:

  1. ADD app.tar.gz .

该代码解压app.tar.gz并复制到当前上下文目录下。

RUN(运行命令)

RUN 指令是用来执行命令行命令的。RUN 指令在定制镜像时是最常用的指令之一。格式有两种

  • shell格式

格式: RUN <命令>
示例:

  1. RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • exec格式

格式: RUN [“可执行文件”, “参数1”, “参数2”]
示例:

  1. RUN ["/bin/bash", "-c","echo hello"]

每条run指令在当前基础镜像执行,并且提交新镜像。当命令比较长时,可以使用 “/“ 换行。

注意:当你想要运行多个命令像shell脚本那样,不能把每个命令都对应成一个RUN,这样会出错,
而是应该用 && 去连接多个命令,因为Dockerfile 中每一个指令都会建立一层,镜像是多层存储。

CMD (容器启动命令)

CMD 指令是用于指定默认的容器主进程的启动命令的,但是每个容器只能执行一条CMD命令,多个CMD命令时,只最后一条被执行。
格式:

  • shell 格式:CMD <命令>
  • exec 格式:CMD [“可执行文件”, “参数1”, “参数2”…]
  • 参数列表格式:CMD [“参数1”, “参数2”…]。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

示例:

  1. CMD [ "curl", "-s", "http://www.baidu.com" ]

ENTRYPOINT (入口点)

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令然后传给指定的命令。
示例:

  1. ENTRYPOINT [ "curl", "-s", "http://www.baidu.com" ]

和CMD不同的是,使用docker run 后面指定的命令行参数,参数会传给ENTRYPOINT,进一步传给curl。

EXPOSE (暴露端口)

仅仅只是声明端口,并不会把端口映射出去,在启动容器时需要通过 -P 参数让 Docker 主机分配一个端口转发到指定的端口。使用 -p 参数则可以具体指定主机上哪个端口映射过来。
示例:

  1. EXPOSE 8080

声明了一个需要暴露的端口号8080,在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

ENV (设置环境变量)

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
示例:

  1. ENV VERSION=1.0

声明一个环境变量,版本号=1.0

WORKDIR (指定工作目录)

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。
示例:

  1. WORKDIR /app

声明后面指令运行的目录是在/app目录下。

示例Dockerfile

  1. FROM java:8
  2. LABEL description="this is project description"
  3. VOLUME /tmp
  4. ADD app-web-1.0.jar app.jar
  5. ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
  6. EXPOSE 8080

这里是一段SpringBoot微服务项目的Dockerfile示例。
首先用FROM指令指定基础镜像是java,版本8,
接下来用LABEL指定描述项目信息,定义匿名卷是/tmp
然后把项目编译的jar包复制到镜像中并改名为app.jar,
最后设置项目入口点是用java -jar 运行项目,-D指定启动参数使用urandom加快随机数生成效率。
EXPOSE 8080 暴露项目端口号是8080,这里只是一个端口说明,并没有实际的进行端口映射,除非docker run时使用-P参数进行随机映射。

Docker Compose

介绍

用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
Compose 恰好满足了这样的需求,它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
Compose 中有两个重要的概念:

  • 服务 (service):一个应用容器,实际上可以运行多个相同镜像的实例。
  • 项目 (project):由一组关联的应用容器组成的一个完整业务单元。

可见,一个项目可以由多个服务(容器)关联而成,Compose 面向项目进行管理。
docker-compose 命令的基本的使用格式是

  1. docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]

命令选项

  • -f, —file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定。
  • -p, —project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
  • —verbose 输出更多调试信息。
  • -v, —version 打印版本并退出。

    命令说明

    build

    构建(重新构建)项目中的服务容器。

config

验证 Compose 文件格式是否正确,若正确则显示配置,若格式错误显示错误原因。

down

此命令将会停止 up 命令所启动的容器,并移除网络。

exec

进入指定的容器。

help

获得一个命令的帮助。

images

列出 Compose 文件中包含的镜像。

kill

通过发送 SIGKILL 信号来强制停止服务容器。
支持通过 -s 参数来指定发送的信号,例如通过如下指令发送 SIGINT 信号。

  1. docker-compose kill -s SIGINT

logs

查看服务容器的输出。

pause

暂停一个服务容器

port

打印某个容器端口所映射的公共端口。

ps

列出项目中目前的所有容器。

pull

拉取服务依赖的镜像。

push

推送服务依赖的镜像到 Docker 镜像仓库。

restart

重启项目中的服务。

rm

删除所有(停止状态的)服务容器。推荐先执行 docker-compose stop 命令来停止容器。

run

在指定服务上执行一个命令。
选项

  • -d 后台运行容器。
  • —name NAME 为容器指定一个名字。
  • —entrypoint CMD 覆盖默认的容器启动指令。
  • -e KEY=VAL 设置环境变量值,可多次使用选项来设置多个环境变量。
  • -u, —user=”” 指定运行容器的用户名或者 uid。
  • —no-deps 不自动启动关联的服务容器。
  • —rm 运行命令后自动删除容器,d 模式下将忽略。
  • -p, —publish=[] 映射容器端口到本地主机。
  • —service-ports 配置服务端口并映射到本地主机。
  • -T 不分配伪 tty,意味着依赖 tty 的指令将无法运行。

scale

设置指定服务运行的容器个数。
通过 service=num 的参数来设置数量。例如:

  1. docker-compose scale web=3 db=2

将启动 3 个容器运行 web 服务,2 个容器运行 db 服务。

start

启动已经存在的服务容器。

stop

停止已经处于运行状态的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器。

top

查看各个服务容器内运行的进程。

unpause

恢复处于暂停状态中的服务。

up

该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。
如果使用 docker-compose up -d,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。
选项:

  • -d 在后台运行服务容器。
  • —no-color 不使用颜色来区分不同的服务的控制台输出。
  • —no-deps 不启动服务所链接的容器。
  • —force-recreate 强制重新创建容器,不能与 —no-recreate 同时使用。
  • —no-recreate 如果容器已经存在了,则不重新创建,不能与 —force-recreate 同时使用。
  • —build 重新创建镜像,然后生成容器。
  • —no-build 不自动构建缺失的服务镜像。
  • -t, —timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。

version

格式为 docker-compose version。
打印版本信息。

示例docker-compose.yml

  1. version: '3'
  2. services:
  3. # 授权认证服务
  4. authentication-server:
  5. image: 192.168.205:9004/authentication-server:latest
  6. container_name: authentication-server
  7. restart: always
  8. network_mode: host
  9. ports:
  10. - 8004:8004
  11. env_file: .env
  12. environment:
  13. TZ: Asia/Shanghai
  14. depends_on:
  15. - system-user-service
  16. # 系统用户服务
  17. system-user-service:
  18. image: 192.168.205:9004/system-user-web:latest
  19. container_name: ervice-system-user
  20. restart: always
  21. network_mode: host
  22. ports:
  23. - 8051:8051
  24. env_file: .env
  25. environment:
  26. TZ: Asia/Shanghai

首先定义了docker-compose的版本为3,
然后定义了两个服务,一个是系统用户服务,一个是授权认证服务。
image指定镜像名称,container_name指定运行的容器名,
restart:always表示启动docker时自动启动服务,network_mode指定网络模式,ports指定映射端口,env_file指定环境变量的文件,environment设置环境变量,
depends_on指定依赖的服务,这里授权认证服务依赖系统用户服务,所以系统用户服务会优先启动。
之后我们会用docker-compose up -d —build 命令启动服务 -d表示后台运行,—build表示重新创建镜像生成容器。

参考

https://zhuanlan.zhihu.com/p/50071898
https://yeasy.gitbook.io/docker_practice/image/build
https://www.jianshu.com/p/658911a8cff3