🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 一 docker镜像构建说明 ### A. 两种构建方式 1. 手动构建docker镜像 2. 自动构建docker镜像[dockerfile] ### B. 构建步骤 * **手工构建步骤** 1. 启动容器安装软件服务 2. 将安装好服务的容器commit提交为镜像 3. 启动新容器来测试新提交的镜像 * **自动构建步骤** 1. 编写dockerfile文件 2. 通过build命令使用该dockerfile构建镜像 3. 启动新容器来测试新提交的镜像 ### C. dockerfile命令集 | 指令 | 功能 |特殊说明| | --- | --- | --- | | FROM | 指定基础镜像 | 必须有 | | MAINTAINER | 指定维护者信息 | 可以没有 | | ENV | 设置环境变量 | 可被后面的指令使用 | | COPY | 复制文件到容器 | | | ADD | 复制文件到容器 | 压缩文件会自动解压 | | WORKDIR | 设置当前工作目录 | 类似linux的cd命令 | | VOLUME | 设置卷,挂载主机目录 | 需'-v'配合 | | EXPOSE | 指定对外的端口 | 默认不暴露,需"-P"配合 | | RUN | 运行指定的命令 | 在用于容器创建过程中执行命令 | | CMD | 容器启动后执行的命令 | 容易被替换 | | ENTRYPOINT | 容器启动后执行的命令 | 无法被替换 | [两种命令方式以及run,cmd,ENTRYPOINT的关系说明](https://www.cnblogs.com/CloudMan6/p/6875834.html) ## 二 手动构建docker镜像 案例以cnetos6.9为基础镜像,制作含有nginx的镜像 ### A. 环境准备 ```sh docker container rm `docker container ls -q -a` docker volume rm `docker volume ls -q` docker run -it --name noah-nginx centos:7.4 ``` ### B. 在容器中执行操作 ``` rm /etc/yum.repos.d/* -f curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo yum install -y nginx echo 'this nginx test pag' >/usr/share/nginx/html/index.html exit ``` ### C. 打包为新镜像`conmit` ```sh docker commit noah-nginx c7-nginx:v1 [root@docker01 ~]# docker image ls c7-nginx REPOSITORY TAG IMAGE ID CREATED SIZE c7-nginx v1 f823aff3828d 39 seconds ago 388MB ``` ### D. 以新镜像创建容器 ```sh docker run -d --name nginx-test -p 880:80 c7-nginx:v1 nginx -g "daemon off;" [root@docker01 ~]# curl 127.0.0.1:880 this nginx test pag ``` 已经通过自己手动构建的镜像创建了新容器,并且成功运行和访问 ## 三 自动构建docker镜像[dockerfile] 相对于手动制作的docker镜像,使用dockerfile构建的镜像有以下优点: 1. dockerfile只有几kb,便于传输 2. 使用dockerfile构建出来的镜像,在运行容器的时候,不用指定容器的初始命令 3. 支持更多的自定义操作 接下来通过dockerfile构建一个nginx镜像 ### A. 环境准备 ```sh docker container rm `docker container ls -q -a` docker volume rm `docker volume ls -q` mkdir -p /data/docker-file/c7-nginx/ cd /data/docker-file/c7-nginx/ ``` ### B. 编写dockerfile镜像 1. 编写dockerfile ```sh cat >dockerfile <<EOF FROM centos:7.4 RUN rm -f /etc/yum.repos.d/*.repo RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo RUN yum clean all && yum makecache RUN yum install -y nginx RUN echo 'this nginx test pag' >/usr/share/nginx/html/index.html CMD nginx -g "daemon off;" EOF ``` 2. docker build构建镜像 `docker build -t c7-nginx:v2 .` 3. 启动新容器来测试新构建的镜像 ```sh docker run -d --name nginx-test -p 980:80 c7-nginx:v2 nginx -g "daemon off;" [root@docker01 ~]# curl 127.0.0.1:980 this nginx test pag ``` ## 四 CMD|ENTRYPOINT和两种格式 RUN、CMD 和 ENTRYPOINT 这三个 Dockerfile 指令看上去很类似,很容易混淆。简单的说他们的**区别**: 1. RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。 2. CMD 设置容器启动后默认执行的命令及其参数. 但 CMD 能够被 `docker run` 后面跟的命令行参数替换。 3. ENTRYPOINT 配置容器启动时运行的命令。 4. 都可以使用两种命令格式:`Shell 和 Exec` ### **A. Shell 和 Exec 命令格式** 可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式 **CMD 和 ENTRYPOINT 推荐使用 Exec 格式**,因为指令可读性更强,更容易理解。RUN 则两种格式都可以。 1. 两种格式语法 * Shell 格式: `<instruction> <command>` ```sh RUN apt-get install python3   CMD echo "Hello world"   ENTRYPOINT echo "Hello world" ``` * Exec 格式: `<instruction> ["executable", "param1", "param2", ...]` ```sh RUN ["apt-get", "install", "python3"] CMD ["/bin/echo", "Hello world"] ENTRYPOINT ["/bin/echo", "Hello world"] ``` 2. Shell格式详解 当指令执行时,shell 格式底层会调用 /bin/sh -c ,例如下面的 Dockerfile 片段: ```sh ENV name Noah luo   ENTRYPOINT echo "Hello, $name"  ``` 执行 docker run 将输出:"Hello, Noah luo" 注意环境变量 `name` 已经被值 `Noah luo` 替换。 3. Exec格式详解 当指令执行时,会直接调用 ,不会被 shell 解析, 例如下面的 Dockerfile 片段: ```sh ENV name Noah luo ENTRYPOINT ["/bin/echo", "Hello, $name"] ``` 运行容器将输出: "Hello, $name" 注意环境变量“name”没有被替换,如果希望使用环境变量,照如下修改 ```sh ENV name Noah luo ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"] ``` 运行容器将输出: 'Hello, Noah luo' ### B. CMD命令详解 CMD 指令允许用户指定容器的默认执行的命令,此命令会在容器启动且 docker run 没有指定其他命令时运行。 * 如果 docker run 指定了其他命令,CMD 指定的默认命令将被忽略。 * 如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效。 1. CMD 有三种格式: 1. Exec 格式:`CMD ["executable","param1","param2"] ` 3. Shell 格式:`CMD command param1 param2 ` 2. ENTRYPOINT参数格式:`CMD ["param1","param2"]` 专为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式,详见 ENTRYPOINT部分说明。 2. 使用举例 Dockerfile 片段:`CMD echo "Hello world" `,运行容器 `docker run -it [image] `将输出:`Hello world `. 但当后面加上一个命令,比如`docker run -it [image] /bin/bash`,CMD 会被忽略掉,命令 bash 将被执行 ### C. ENTRYPOINT命令详解 ENTRYPOINT 指令可让容器以应用程序或者服务的形式运行, 与 CMD都可以指定要执行的命令及其参数. 不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。 1. ENTRYPOINT 有两种格式: 两种格式的效果差别很大 * Exec 格式:`ENTRYPOINT ["executable", "param1", "param2"] ` * Shell 格式:`ENTRYPOINT command param1 param2 ` 2. Exec 格式详解 ENTRYPOINT 的 Exec 格式用于设置要执行的命令及其参数,同时可通过 CMD 提供额外的参数。 ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。 Dockerfile 片段如下: ``` ENTRYPOINT ["/bin/echo", "Hello"] CMD ["world"] ``` 当容器通过 `docker run -it [image] `启动时,输出为:`Hello world ` 而如果通过 `docker run -it [image] noah` 启动,则输出为:`Hello noah` 3. Shell 格式 ENTRYPOINT 的 Shell 格式会忽略任何 CMD 或 docker run 提供的参数。 ### **D. 最佳实践总结** 1. 如果 Docker 镜像的用途是运行应用程序或服务,如运行MySQL,优先使用 Exec 格式的 ENTRYPOINT 指令。 CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。 2. 如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。