{"msg":"操作成功","code":200,"data":{"createBy":"admin","createTime":"2021-05-19 09:44:34","updateBy":"admin","updateTime":"2025-09-12 14:07:59","remark":null,"params":{"@type":"java.util.HashMap"},"id":59,"articleTitle":"Docker（五）Dockerfile","articleUrl":"docker_dockerfile","articleThumbnail":"https://www.asumimoe.com/imgfiles/20220906/713782e83c4e4b9bbf2d588c2789e07d.jpg","articleFlag":"0","draftStatus":"1","reprintStatement":"1","articleSummary":"制作属于自己的Docker镜像，一般有两种方式，第一种为commit方式，利用已有的镜像，运行后安装定制自己需要的环境，然后生成镜像；另一种就是build方式，通过编写Dockerfile命令脚本进行生成镜像。","articleContent":"## 利用Dockerfile制作镜像\n\nDockerfile是用来制作Docker镜像的文本文件，是由一条条构建镜像所需的指令和参数构成的脚本。\n\n### Dockerfile编写事项\n\n- \\# 井号进行备注\n- 每条保留字指令都必须是大写且后面要跟随至少一个参数！\n- 第一个非注释行必须是FROM指令\n- 编写Dockerfile必须在一个目录下进行，这个目录称之为 工作目录（WORKSPACE）\n- Dockerfile文件命名的首字母必须大写\n- 制作镜像所要用的文件必须放在工作目录或者工作目录的子目录之下，不能放在父目录\n- 可以通过隐藏文件 .dockeringnore 来指定不要放入到镜像中的文件，一行是一个文件，可以用通配符\n- 基于dockerfile做镜像，本质上还是基于一个现有的镜像做新镜像，每条指令都会创建一个新的镜像层并对镜像进行提交。\n\n### Dockerfile执行的大致流程\n\n- docker从基础镜像运行一个容器\n- 执行一条指令并对容器作出修改\n- 执行类似docker commit的操作提交一个新的镜像层\n- docker再基于刚提交的镜像运行一个新容器\n- 执行dockerfile中的下一条指令直到所有指令都执行完成\n\n### 常用命令\n\n1. FROM\n\n   ```dockerfile\n   指定使用哪个基础镜像\n   FROM REPOSITORY：TAG\n   ```\n\n2. ENV\n\n   ```dockerfile\n   设置环境变量:\n   1）ENV 变量名=变量值（可以同时指定多个变量，用空格分隔）\n   2）ENV 变量名 变量值\n   引用变量加$\n   ```\n\n3. LABEL\n\n   ```dockerfile\n   设置标签、注释\n   LABLE key=value\n   ```\n\n4. RUN\n\n   ```dockerfile\n   容器构建时执行的命令 \n   RUN command\n   可以执行多个命令\n   1）RUN command1;command2\n   2）RUN command1&&command2\n   \n   注意：\n   1）因为docker镜像是分层机制，应当尽量减少层次，所以如果在创建镜像的时候需要执行多个命令，建议使用一个RUN 指令，执行多个命令。\n   2）RUN 指令默认是在shell中环境中执行，docker镜像当中的shell类型默认为/bin/sh/ -c\n   ```\n\n5. COPY\n\n   ```dockerfile\n   复制到文件到镜像中\n   COPY src dest\n   注意：  \n   - 源文件路径用相对路径，目标一般用绝对路径\n   - 也可以通配符\n   - 源文件必须在工作目录或者工作目录的子目录中\n   - 目标路径可以不存在，会自动创建\n   - 如果源文件是一个目录，会自动递归复制目录下的文件到目标位置，但是目录自身不会复制\n   - 如果复制多个文件，或者源文件中用了通配符，那么目标路径必须以 / 为结尾  \n   ```\n\n6. WORKDIR\n\n   ```dockerfile\n   指定工作目录\n   WORKDIR path\n   ```\n\n7. EXPOSE\n\n   ```dockerfile\n   暴露端口\n   EXPOSE port\n   注意：这里声明暴露端口并不是说在启动容器的时候，容器会自动暴露相关的端口，而是仍需要管理员使用-P 选项进行端口暴露并连接\n   ```\n\n8. VOLUME\n\n   ```dockerfile\n   声明需要映射的数据卷 \n   VOLUME path\n   注意：如果在构建镜像时使用volume声明了需要暴露的数据卷路径，在启动容器的时候回自动和宿主机的一个目录进行绑定!docker management volume类型并且不需要加-v选项\n   ```\n\n9. ADD\n\n   ```dockerfile\n   和copy相似，也是复制文件到镜像中\n   ADD src dest\n   注意：ADD可以在网上下载文件到镜像中，也可以复制tar.gz格式的包到镜像中并实现自动解压\n   ```\n\n10. CMD\n\n    ```dockerfile\n    执行命令，一个Dockerfile可以有多个CMD指令，但只有最后一个CMD指令生效\n    三种格式：\n    1）CMD command 在shell中执行相关的命令，默认类型为/bin/sh -c\n    2）CMD [\"command\",\"parameter1\",\"parameter2\"]\n    3）CMD [\"parameter1\",\"parameter2\"] 需要和ENTRYPOINT命令一起使用，CMD的选项会被当做参数传递给ENTRYPOINT指令\n    ```\n\n11. ENTRYPOINT\n\n    ```dockerfile\n    执行命令\n    两种格式：\n    1）ENTRYPOINT cat test –> /bin/sh -c cat test\n    2）ENTRYPOINT [\"command\",\"parameter1\",\"parameter2\"]\n    注意：CMD和ENTRYPOINT命令启动的都是pid为1的进程\n    ```\n\n12. ONBUILD\n\n    ```dockerfile\n    定义触发器：其他人以此镜像重新制作镜像时会触发触发器定义的命令\n    ```\n\n13. STOPSIGNAL\n\n    ```dockerfile\n    向容器中pid为1的进程发送一个信号，通过这个信号来关闭这个主进程，默认是15信号\n    \n    STOPSIGNAL 数值\n    ```\n\n14. HEALTHCHECK\n\n    ```dockerfile\n    docker daemon检查docker容器是否正常，如果异常会将该容器stop\n    \n    将容器stop的条件\n    \n    1）主进程停止了\n    \n    2）主进程工作在了后台\n    \n    HEALTHCHECK [options] CMD\n    ```\n\n    options：\n\n    ```bash\n    –interval=#s|m          指定健康检查的时间间隔（例如：30s,30m）\n    –timeout=#s|m           指定等待响应的超时时间\n    –start-period=#s|m      指定容器启动多久以后才可以做监控检查\n    –retries=#              指定重试次数\n    ```\n\n    返回值：\n\n    ```dockerfile\n    0：success\n    \n    1：unhealth\n    ```\n\n## build创建镜像\n\nDocker 的 `build` 命令是构建镜像的核心工具。`docker build [OPTIONS] PATH | URL | -`\n\n| 选项                | 说明                                                         | 示例                                               |\n| :------------------ | :----------------------------------------------------------- | :------------------------------------------------- |\n| **`-t, --tag`**     | 为构建的镜像指定**名称和标签**，格式为 `name:tag`。可多次使用为同一镜像设置多个标签。 | `docker build -t myapp:v1 .`                       |\n| **`-f, --file`**    | 指定 **Dockerfile 的路径**。默认情况下，Docker 会查找上下文路径（PATH）下名为 `Dockerfile` 的文件。 | `docker build -f ./docker/Dockerfile.prod .`       |\n| **`--build-arg`**   | 设置**构建时的变量**，其值可以在 Dockerfile 的 `ARG` 指令中使用。 | `docker build --build-arg VERSION=2.3.1 .`         |\n| **`--no-cache`**    | **禁用缓存**，强制重新构建所有层。Docker 默认会缓存已构建的层以加速后续构建。 | `docker build --no-cache -t myapp:v1 .`            |\n| **`--pull`**        | 始终尝试**从镜像仓库拉取最新版本的基础镜像**，确保使用最新的基础镜像。默认情况下，Docker 会使用本地缓存的基础镜像。 | `docker build --pull -t myapp:v1 .`                |\n| **`--target`**      | 在**多阶段构建**中，指定要构建的目标阶段。                   | `docker build --target builder -t myapp-builder .` |\n| **`--rm`**          | 构建成功后**删除中间容器**。此选项默认启用。                 | `docker build --rm=true .`                         |\n| **`--force-rm`**    | **无论构建成功与否，都删除中间容器**。                       | `docker build --force-rm .`                        |\n| **`-q, --quiet`**   | **安静模式**，构建成功后只输出镜像 ID。                      | `docker build -q -t myapp:v1 .`                    |\n| **`--squash`**      | **将所有构建层压缩为一层**（实验性功能）。注意，压缩后新层将无法在多个镜像之间共享。 | `docker build --squash -t myapp:v1 .`              |\n| **`--iidfile`**     | 将生成的**镜像 ID 写入指定文件**，常用于自动化脚本。         | `docker build --iidfile=image.id .`                |\n| **`--network`**     | 设置构建期间 `RUN` 指令使用的**网络模式**（如 `default`, `host`, `none`）。 | `docker build --network host .`                    |\n| **`-m, --memory`**  | 限制构建过程使用的**内存大小**。                             | `docker build -m 2g .`                             |\n| **`--shm-size`**    | 设置构建过程中 `/dev/shm` 的**共享内存大小**，默认为 64MB。  | `docker build --shm-size=1g .`                     |\n| **`--cpuset-cpus`** | 指定构建过程可以使用的 **CPU 核心**（如 \"0,1\"）。            | `docker build --cpuset-cpus=\"0,1\" .`               |\n| **`--label`**       | 为生成的镜像设置**元数据标签**。                             | `docker build --label \"`                           |\n\n### 利用Dockerfile创建一个LNMP镜像\n\n1. 拉取centos7镜像并初始化镜像\n\n   ```dockerfile\n   FROM centos:7\n   ENV container docker\n   RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \\\n   systemd-tmpfiles-setup.service ] || rm -f $i; done); \\\n   rm -f /lib/systemd/system/multi-user.target.wants/*;\\\n   rm -f /etc/systemd/system/*.wants/*;\\\n   rm -f /lib/systemd/system/local-fs.target.wants/*; \\\n   rm -f /lib/systemd/system/sockets.target.wants/*udev*; \\\n   rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \\\n   rm -f /lib/systemd/system/basic.target.wants/*;\\\n   rm -f /lib/systemd/system/anaconda.target.wants/*;\n   VOLUME [ \"/sys/fs/cgroup\" ]\n   CMD [\"/usr/sbin/init\"]\n   ```\n\n   ```shell\n   # 执行dockerfile文件制作镜像\n   docker build -t centos:7.0 .\n   ```\n\n   \n\n2. 编写制作LNMP架构的Dockerfile\n\n   ```dockerfile\n   FROM local/c7-systemd\n   COPY local.repo /etc/yum.repos.d/\n   COPY wordpress /var/www/html/\n   RUN yum -y install nginx mariadb-server php php-mysql; yum clean all; systemctl restart mariadb httpd;systemctl enable mariadb nginx\n   EXPOSE 80 3306\n   CMD [\"/usr/sbin/init\"]\n   \n   （1）使用第一步创建出来的镜像\n   （2）把local.repo文件发送到镜像中，因为镜像文件没有mariad数据库\n   local.repo文件内容\n   \n   [local]\n   name=local\n   enabled=1\n   gpgcheck=0\n   baseurl=https://mirrors.aliyun.com/centos/7/os/x86_64/\n   \n   （3）把配置好的wordpress安装包复制到网站根目录下\n   （4）下载LNMP架构\n   （5）暴露80 和3306 端口\n   （6）启动\n   ```\n\n### 虚悬镜像\n\n仓库名和标签名都是none的镜像。构建或删除时出错会产生虚悬镜像。\n\n```shell\ndocker image ls -f dangling=true # 列出所有的虚悬镜像\ndocker image prune # 删除所有虚悬镜像\n```\n\n","categoryId":9,"viewCount":1575,"categoryName":"Docker","author":"球接子","authorAvatar":null,"tagIds":[9],"tagNames":["Docker"]}}