Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker 学习笔记 - Day2 #14

Open
JZLeung opened this issue Sep 28, 2017 · 1 comment
Open

Docker 学习笔记 - Day2 #14

JZLeung opened this issue Sep 28, 2017 · 1 comment
Labels

Comments

@JZLeung
Copy link
Owner

JZLeung commented Sep 28, 2017

Dockerfile

虽然我们确实能快速搭建了一个 lnmp 的环境,但是每次切换宿主机时,都要执行多个步骤:

  1. 启动 mysql 服务器
  2. 启动 php 服务器
  3. 进入 php 容器修改配置
  4. 启动 nginx 服务器
    怎么说都还是麻烦。如果能一键启动的话,那就更好了。

Dockerfile 就可以解决这样的问题。

要使用 Dockerfile ,先要了解一下这到底是个什么东西。

什么是 Dockerfile?

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.

Dockerfile是一个文本文档,其中包含用户可以在命令行上调用以组合镜像的所有命令。使用docker构建用户可以创建一个自动构建,连续执行几个命令行指令。

Dockerfile 常用命令

FROM

语法: FROM <image> [AS <name>] or FROM <image>[:<tag>][AS ] or FROM <image>[@<digest>][AS ]

注意:FROM 命令必须是 Dockerfile 的首个命令,但可以在一个 Dockerfile 中出现多次。

说明: 该命令定义了使用哪个基础镜像启动构建流程。基础镜像可以为任意镜像。

MAINTAINER

语法: MAINTAINER <NAME>

说明: 设置生成镜像的作者名字。

RUN

语法:

  • RUN <command> (shell形式,/bin/sh -c 或者是 Windows 的 cmd /S /C )
  • RUN ["<executable>", "<param1>", "<param2>"] (exec 形式)

说明:

RUN命令将在当前image中执行任意合法命令并提交执行结果。

RUN 指令缓存不会在下个命令执行时自动失效。

RUN命令用于创建镜像(在之前commit的层之上形成新的层)。

ADD

语法:

  • ADD <src> [<src> ...] <dest>
  • ADD ["<src>", ... "<dest>"] (路径中包含空格的必须使用该形式)

注意:ADD只有在build镜像的时候运行一次,后面运行container的时候不会再重新加载了。

说明: 从 src 拷贝新的文件或文件夹或远程文件 URL 到镜像的文件系统的路径 dest 中。

  • 所有拷贝到 container 中的文件和文件夹权限为 0755 , uid 和 gid 为0。
  • 如果文件是可识别的压缩格式,则 docker 会自动解压缩。
  • 如果 src 为本地文件或文件夹,则必须相对于 docker build <PATH> 中的 <PATH> 目录中。
  • dest 是一个绝对路径,或者相对于 WORKDIR ,如果 <dest> 不存在则会自动创建。

COPY

  • COPY <src> [<src> ...] <dest>
  • COPY ["<src>", ... "<dest>"] (路径中包含空格的必须使用该形式)

COPY 的语法和使用说明和 ADD 基本一致,但是在遇见压缩包时, COPY 很直接的拷贝到容器当中,而不会解压。 Docker 团队建议大多数情况下使用 COPY。

CMD

语法:

  • CMD ["<executable>","<param1>","<param2>"] exec 形式,比较好的形式。
  • CMD ["<param1>","<param2>"] 作为 ENTRYPOINT 的默认参数。
  • CMD <command> <param1> <param2> shell 形式。

注意:Dockerfile 中只能有一个 CMD 指令,如果有多个则只有最后一个生效。

说明:

CMD 命令最主要的目的是提供一个默认的执行容器。

和RUN命令相似,CMD可以用于执行特定的命令。和RUN不同的是,这些命令不是在镜像构建的过程中执行的,而是在用镜像构建容器后被调用。

如果 CMD 用于为 ENTRYPOINT 提供默认参数时, CMD 和 ENTRYPOINT 指令应该规定为 JSON 数组格式。

docker run command 的命令匹配到 CMD command 时,会替换CMD执行的命令,即 docker run命令如果指定了参数会把CMD里的参数覆盖: (这里说明一下,如:docker run -it ubuntu /bin/bash 命令的参数是指/bin/bash 而非 -it ,-it只是docker 的参数,而不是容器的参数,以下所说参数均如此。)

ENTERYPOINT

语法:

  • ENTRYPOINT ["<executable>", "<param1>", "<param2>"] (exec 形式,推荐)
  • ENTRYPOINT <command> <param1> <param2> (shell 形式)

注意:Dockerfile 中只能有一个 ENTRYPOINT 指令,如果有多个则只有最后一个生效。

说明:

配置容器启动后执行的命令,并且参数不可被 docker run 提供的参数覆盖。

如果结合 CMD 使用时,要使用 exec 的形式,即:

ENTRYPOINT ["echo"]
CMD ["HELLO_WORLD"]

这是 CMD 命令的内容则不是一个完整的指令,而是为 ENTRYPOINT 命令提供默认参数,该参数可以被 docker run 后的参数所覆盖。

EXPOSE

语法: EXPOSE <port> [<port> ...]

说明: 通知 Docker 在运行时监听指定的端口。主机上要用还得在启动container时,做host-container的端口映射。

ENV

语法:

  • ENV <key> <value>
  • ENV <key>=<value> [<key>=<value> ...]

说明:

该指令将环境变量的 key 设置为 value ,这些值都可以在 Dockerfile 后续的命令中用上,并可以被修改。

VOLUME

语法:

  • VOLUME ["<path>", ...]
  • VOLUME <path> [<path> ...]

说明: 创建一个有具体名称的挂载点,并将其标记为从本机或者其他容器外部的挂载卷。

USER

语法: USER <username | UID>

说明: 指定某个用户运行容器。

WORKDIR

语法: WORKDIR </path/to/workdir>

说明: 设定指令 CMD , RUN , ENTRYPOINT , COPYADD 的工作目录。可以在一个 Dockerfile 中出现多次,如果提供了一个相对路径,那么它将相对于前一个 WORKDIR 指令的路径。

ARG

语法: ARG <name>[=default value>]

说明:

  • 定义一个变量,用户可以在建立的时候通过 docker build 命令使用 —build-arg <varname>=<value> 指定。
  • 多条 ARG 指令可以定义指定的变量,但是在构建成功后取消。
  • 相同名字的环境变量会被 ENV 指令的覆盖。
  • Docker 有一组预定义的 ARG 变量,可以在 Dockerfile 中使用而不需要 ARG 指令。

ONBUILD

语法: ONBUILD <Dockerfile INSTRUCTION>

说明:

  • 当镜像作为另一个镜像构建的基础时,添加一个被延时执行的触发指令。就类似于在子镜像的 Dockerfile 的 FROM 指令下插入了一条命令。
  • ONBUILD 指定的命令在构建镜像时不执行,只在它的子镜像中执行。
  • 任何构建指令都可以被注册为触发器,但 ONBUILD 指令不一定触发 FROM , MAINTAINER 或者 ONBUILD 指令。

Dockerfile 构建镜像

现在将先前搭建 lnmp 的具体步骤一步步写进 Dockerfile 中。

MySQL

FROM mysql

MAINTAINER LeungJZ

ENV MYSQL_ROOT_PASSWORD 123456

EXPOSE 3306

没啥太多的配置,就是简单的配置ROOT密码和暴露3306端口。

构建镜像:

leung@ubuntu:~/docker$ docker build ./mysql/ -t test-mysql
Sending build context to Docker daemon   2.56kB
Step 1/4 : FROM mysql
 ---> 141d24fea983
Step 2/4 : MAINTAINER LeungJZ
 ---> Using cache
 ---> aa6665261e02
Step 3/4 : ENV MYSQL_ROOT_PASSWORD 123456
 ---> Using cache
 ---> 4d482f48a09d
Step 4/4 : EXPOSE 3306
 ---> Using cache
 ---> 385bb10cd49a
Successfully built 385bb10cd49a
Successfully tagged test-mysql:latest

瞬间构建成功。再启动一个容器 docker run --name mysql -p 3306:3306 -d test-mysql ,和以前基本一致。

Php7.1-fpm

FROM php:7.1-fpm

MAINTAINER LeungJZ

COPY php.ini /usr/local/etc/php/conf.d/php.ini

RUN /usr/local/bin/docker-php-ext-install pdo_mysql

EXPOSE 9000

CMD ["php-fpm"]

指定了 php-fpm 的版本为 7.1,并覆盖了我们自定义的 php.ini ,并且安装 pdo_mysql 拓展。

leung@ubuntu:~/docker$ docker build ./php/ -t test-php7
Sending build context to Docker daemon  70.14kB
Step 1/6 : FROM php:7.1-fpm
 ---> 9b44e8b4c8b6
Step 2/6 : MAINTAINER LeungJZ
 ---> Using cache
 ---> 1038ce686af9
Step 3/6 : COPY php.ini /usr/local/etc/php/conf.d/php.ini
 ---> Using cache
 ---> cdbdece75628
Step 4/6 : RUN /usr/local/bin/docker-php-ext-install pdo_mysql
 ---> Using cache
 ---> 8a8cbd9c8ac9
Step 5/6 : EXPOSE 9000
 ---> Using cache
 ---> 1fd3881b6769
Step 6/6 : CMD php-fpm
 ---> Using cache
 ---> 00d178a9351b
Successfully built 00d178a9351b
Successfully tagged test-php7:latest

因为之前构建过一次,所以全都是从缓存中获取,直接就构建完成。

启动: docker run --name php7-fpm --link mysql:mysql -p 9000:9000 -v $PWD/project:/usr/share/nginx/html -d test-php7

nginx

FROM nginx:1.13

MAINTAINER LeungJZ

COPY default.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

ENTRYPOINT ["nginx", "-g", "daemon off;"]

配置就是基础镜像为 1.13 版本的 nginx ,覆盖自定义的 default.conf 配置文件,暴露80端口,并且不以守护进程模式启动。

leung@ubuntu:~/docker$ docker build ./nginx/ -t test-nginx
Sending build context to Docker daemon  4.608kB
Step 1/5 : FROM nginx:1.13
 ---> da5939581ac8
Step 2/5 : MAINTAINER LeungJZ
 ---> Using cache
 ---> 3076338acc32
Step 3/5 : COPY default.conf /etc/nginx/conf.d/default.conf
 ---> Using cache
 ---> bb7ab780e5d4
Step 4/5 : EXPOSE 80
 ---> Using cache
 ---> 38dda9a94ae6
Step 5/5 : ENTRYPOINT nginx -g daemon off;
 ---> Using cache
 ---> 7864bf277ac0
Successfully built 7864bf277ac0
Successfully tagged test-nginx:latest

启动: docker run --name nginx --link php7-fpm:php7-fpm -v $PWD/project:/usr/share/nginx/html -p 80:80 -d test-nginx

访问 http://10.211.55.9/i.php 依旧可以看到熟悉的 phpinfo 的界面。

小结

Dockerfile 可以帮我们减轻了很多配置方面的麻烦,但是启动时,依旧需要绑定很多变量,如挂载卷,映射端口等。虽然只需 run 一次,但是这也是麻烦的。

当然,肯定有解决的办法,就是接下来的 docker-compose 。

@JZLeung JZLeung added the docker label Sep 28, 2017
@mengdodo
Copy link

跟着你学哈哈

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants