本文介绍基于 Dockerfile 和 docker build
命令构建新的 Docker 镜像。
1 第一个 Dockerfile
让我们创建一个目录并编写一个 Dockerfile 文件吧,这是一个包含简单 Web 服务器的 Docker 镜像。
static_web 是存储 Dockerfile 文件的文件夹,称这个目录为构建上下文(build context),Docker 会在构建竟像时将上下文中的文件和目录上传到 Docker 守护进程。
mkdir static_web cd static_web vim Dockerfile
Dockerfile 的内容如下:
# Version: 0.0.1 FROM ubuntu:24.04 LABEL maintainer="lwg0452 <test@test.com>" RUN apt-get update && apt-get install -y nginx RUN echo 'Hi, I am in your container' >usr/share/nginx/html/index.html EXPOSE 80 WORKDIR /usr/sbin ENTRYPOINT ["nginx"] CMD ["-h"] WORKDIR /root ENV TEST=1 USER nginx LABEL version="0.0.1" role="Web Server"
Dockerfile 由一系列的指令和参数构成,每条指令都必须为大写字母(例如 FROM),Dockerfile 中的指令会按照顺序由上到下执行。每条指令都会创建一个新的镜像层,并对镜像进行提交。Docker 答题上按照如下流程执行 Dockerfile 中的指令:
- Docker 从基础镜像运行一个容器;
- 执行一条指令,对容器进行修改;
- 执行类似
docker commit
的操作,提交一个新的镜像层; - Docker 再基于刚提交的镜像运行一个新容器;
- 执行 Dockerfile 中的下一条指令,知道所有指令都执行完毕。
Dockerfile 中以 #
开头的行是注释,Dockerfile 不支持行内注释,例如如下的注释是不合法的:
yum install -y nginx # 安装 Nginx
2 使用 docker build 命令构建新镜像
docker build
命令示例如下:
# 进入 Dockerfile 所在的目录 cd static_web # 执行 docker build 命令,注意命令最后的".",它表示在当前目录寻找 Dockerfile 文件 docker build -t lwg0452/static_web:0.0.1 .
命令输出如下:
docker build
命令构建镜像会用到缓存机制来加速构建过程,当构建步骤没有变化时,Docker 会跳过这些步骤,直接使用之前的构建结果,例如重新执行以上命令,输出如下:
如果希望在构建过程不使用缓存,可以使用 --no-cache
参数:
docker build --no-cache -t "lwg0452/static_web:0.0.1" .
如果希望查看新镜像的构建过程,可以使用 docker history
命令:
docker history lwg0452/static_web:0.0.1
输出如下,其中 <missing>
表示该层已被合并或优化,无法直接看到中间层 ID,但仍然可以看到每个步骤的执行情况:
=> => naming to docker.io/lwg0452/static_web:0.0.1 0.0s root@lwg0452-VMware-Virtual-Platform:~/static_web# docker history lwg0452/static_web:0.0.1 IMAGE CREATED CREATED BY SIZE COMMENT 8aa7a50dd409 4 minutes ago LABEL version=0.0.3 role=Web Server 0B buildkit.dockerfile.v0 <missing> 4 minutes ago USER nginx 0B buildkit.dockerfile.v0 <missing> 4 minutes ago ENV TEST=1 0B buildkit.dockerfile.v0 <missing> 4 minutes ago WORKDIR /root 0B buildkit.dockerfile.v0 <missing> 4 minutes ago CMD ["-h"] 0B buildkit.dockerfile.v0 <missing> 4 minutes ago ENTRYPOINT ["nginx"] 0B buildkit.dockerfile.v0 <missing> 4 minutes ago WORKDIR /usr/sbin 0B buildkit.dockerfile.v0 <missing> 4 minutes ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0 <missing> 4 minutes ago RUN /bin/sh -c echo 'Hi, I am in your contai… 27B buildkit.dockerfile.v0 <missing> 4 minutes ago RUN /bin/sh -c apt-get update && apt-get ins… 55.6MB buildkit.dockerfile.v0 <missing> 4 minutes ago LABEL maintainer=lwg0452 <test@test.com> 0B buildkit.dockerfile.v0 <missing> 2 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 2 months ago /bin/sh -c #(nop) ADD file:6df775300d76441aa… 78.1MB <missing> 2 months ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B <missing> 2 months ago /bin/sh -c #(nop) LABEL org.opencontainers.… 0B <missing> 2 months ago /bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH 0B <missing> 2 months ago /bin/sh -c #(nop) ARG RELEASE 0B root@lwg0452-VMware-Virtual-Platform:~/static_web#
3 Dockerfile 指令
Dockerfile 文件中需要用到许多 Dockerfile 指令,以下表格总结了各个指令的作用和用法:
指令 | 作用 | 示例 |
---|---|---|
FROM |
指定基础镜像 | FROM ubuntu:24.04 |
LABEL |
添加元数据(如维护者信息) | LABEL maintainer="user@example.com" |
RUN |
运行命令并创建新镜像层 | RUN apt-get update && apt-get install -y nginx |
COPY |
复制本地文件到容器(不会自动解压) | COPY index.html /usr/share/nginx/html/ |
ADD |
复制文件(支持自动解压 .tar.gz 和 URL 下载) |
ADD my_archive.tar.gz /app/ |
WORKDIR |
设置工作目录 | WORKDIR /app |
CMD |
指定默认启动命令(可被 docker run 覆盖) |
CMD ["nginx", "-g", "daemon off;"] |
ENTRYPOINT |
指定入口点(不会被 docker run 覆盖) |
ENTRYPOINT ["python", "app.py"] |
ENV |
设置环境变量 | ENV APP_ENV=production |
EXPOSE |
声明容器暴露的端口(但不会自动映射) | EXPOSE 80 |
VOLUME |
定义数据卷(持久化存储) | VOLUME /data |
ARG |
定义构建时变量(仅 docker build 期间有效) |
ARG BUILD_VERSION=1.0 |
ONBUILD |
继承该镜像时执行的指令 | ONBUILD COPY . /app |
USER |
指定容器运行的用户 | USER nginx |
HEALTHCHECK |
定义健康检查机制 | HEALTHCHECK CMD curl --fail http://localhost || exit 1 |
COPY
和ADD
指令复制的文件必须在 Docker 构建上下文(build context) 中,构建上下文是指docker build
命令的当前目录或-f
指定的 Dockerfile 所在目录。Docker 只能访问 上下文内的文件,无法直接访问上下文外的文件。-
ONBUILD
只会在继承该镜像的 Dockerfile 中触发,不会影响当前构建的镜像。 - 如果子镜像
Dockerfile
里FROM
了my_base
,但不希望执行ONBUILD
指令,可以手动 清除它们:
FROM my_base ONBUILD OFF
4 将镜像推送到 DockerHub
可以通过 docker push
命令将镜像推送到 DockerHub,这样所有人就能使用这个镜像了。
docker push lwg0452/static_web:0.0.1
lwg0452
需要替换成自己的镜像 ID。
- 本文固定链接: https://weiguangli.com/archives/782
- 转载请注明: lwg0452 于 Weiguang的博客 发表