一、编写 Dockerfile 文件
如下是一个简单的 Dockerfile 脚本文件,构建了一个支持 vim 命令的 ubuntu 镜像:
# 指定基础镜像为 ubuntu:22.04
FROM ubuntu:22.04
# 更新 apt
RUN apt update
# 安装 vim
RUN apt install -y vim
Dockerfile 中使用命令关键字来执行相关操作,关键字必须大写:
- FROM :一般为 Dockerfile 中第一行非注释代码,表示我们的镜像是基于哪个镜像来创建的。
- RUN :用于在构建镜像的时候运行 Shell 命令,如上运行了两条命令,用来安装 vim。
Dockerfile 中每?条 RUN 指令都会在镜像上构建?层,因此为了减?镜像?件??,我们可以将多个 RUN 命令合并为一条命令,从而减少镜像的层数。
FROM ubuntu:22.04
# 更新 apt 并安装 vim
RUN apt update && apt install -y vim
二、构建镜像
# docker build -t <镜像名称>:<版本标签> -f <脚本名> <脚本路径>
docker build -t liwy-ubuntu:1.0 \
-f Dockerfile .
- -t :指定构建的镜像的名称与版本标签;
- -f :执行脚本文件名称,省略时,默认查找名为 Dockerfile 的脚本。
- . :这个参数指定了 Dockerfile 所在的路径,. 表示当前目录。
三、Dockerfile 常用关键字
1. FROM
# 指明要基于哪个镜像创建
# FROM <image>[:<tag>]
# <tag> 默认为 latest
FROM ubuntu:22.04
2. LABEL
# 设置镜像描述信息
# LABEL <key>=<value> [<key>=<value> ...]
LABEL version="1.0" maintainer="LIWY"
LABEL description="镜像说明"
3. WORKDIR
# 设置工作目录
# 此后的 RUN、CMD、ENTRYPOINT、COPY、ADD 等命令将在这个工作目录下执行。
# 如果设置的目录不存在会自动创建。
# WORKDIR <路径>
WORKDIR /home/liwy
4. USER
# 指定执行命令的用户与用户组
# USER <user>[:<group>]
USER liwy:liwy
5. ENV
# 设置环境变量
# ENV key value
# ENV key1=value1 key2=value2
# 设置一个名为 WORK_HOME 的环境变量
ENV WORK_HOME /home/liwy
环境变量是一直存在于镜像中的,运行容器时依然存在。
环境变量可以在后续的 RUN、WORKDIR 等命令中使用:
# 引用 WORK_HOME 环境变量
WORKDIR $WORK_HOME
如果在 Dockerfile 中使用 ENV 指令设置了环境变量,那么在使用 docker run 命令的时候,可以使用 -e 参数覆盖 Dockerfile 中设置的值。这在需要动态配置容器时非常有用,比如根据运行时的条件来设置不同的环境变量值。
# 设置 Spring Boot 配置文件环境变量
ENV SPRING_PROFILES_ACTIVE=prod
在运行容器的时候,可以使用 -e 参数覆盖 Dockerfile 中的环境变量:
docker run -d \
-e SPRING_PROFILES_ACTIVE=dev \
liwy-image
6. ARG
# 定义变量
# ARG key[=value]
ARG VERSION=latest
ARG 定义的变量只在构建过程中有效,构建完成后不会被保留在最终的镜像中。
构建过程中,ARG 定义的参数可以用于在 Dockerfile 中的各个指令中。它对于在构建时动态地传递参数非常有用。
# 定义构建参数
ARG VERSION=latest
ARG BUILD_DATE
# 使用构建参数设置环境变量
ENV APP_VERSION=$VERSION
ENV BUILD_DATE=$BUILD_DATE
在构建的时候,可以通过 --build-arg 传递参数:
docker build \
--build-arg VERSION=1.0.0 \
--build-arg BUILD_DATE=$(date) \
-t liwy-image .
7. COPY
# 拷贝文件或目录到镜像中
# COPY <src> <dest>
COPY liwy-project-0.0.1.jar \
/opt/app.jar
8. ADD
# 拷贝文件或目录到镜像中
# 支持自动下载 url 和自动解压
# ADD <src> <dest>
ADD https://example.com/file.tar.gz /tmp/
9. RUN
# 在构建镜像时执行 shell 命令
# shell 格式
# RUN <command>
RUN apt update && apt install -y vim
RUN mkdir -p /home/liwy/docker
# Exec 格式
# RUN [<command>, ...]
RUN ["apt", "update", "&&", "apt", \
"install", "-y", "vim"]
RUN 命令会在执行 docker build 命令的时候执行。每?条 RUN 指令都会在镜像上构建?层,所以为了减?镜像?件??,可以将多个 RUN 命令合并为一条命令,从而减少镜像的层数。但是合并会降低可读性,所以需要根据实际情况权衡可读性和减小层数之间做个平衡。
10. VOLUME
# 匿名挂载,在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
# VOLUME <路径1> <路径2> ...
# VOLUME ["<路径1>", "<路径2>"...]
VOLUME /data
VOLUME /config
11. EXPOSE
# 声明对外暴漏的端口
# EXPOSE <port> [<port>/<protocol>...]
EXPOSE 80 443
# 指定端口和协议
EXPOSE 8080/tcp
12. ENTRYPOINT
用于指定容器启动时执行的命令。在一个 Dockerfile 中只能有一个 ENTRYPOINT 命令。如果定义了多个 ENTRYPOINT,则只有最后一个生效,而之前的将被忽略。
# Shell格式
# ENTRYPOINT <command>
# Exec格式
# ENTRYPOINT ["参数1", "参数2", ...]
# 启动容器后打印"Hello Liwy!"
ENTRYPOINT ["echo", "Hello Liwy!"]
13. CMD
用于为容器指定默认的执行命令或应用程序。当容器启动时,这个命令将被执行,可以用来启动容器中的应用程序。
# Shell格式
# CMD <command>
# Exec格式
# CMD ["参数1", "参数2", ...]
# 运行容器时默认启动 tomcat
CMD ["catalina.sh", "run"]
如果在 Dockerfile 中存在多个 CMD 命令,只有最后一个会生效。
当我们通过 docker run 启动容器时,如果指定了 <cmd> 参数,则 Dockerfile 中的 CMD 命令将被覆盖。
docker run -it -p 8080 tomcat /bin/bash
如上 /bin/bash 就是 docker run 之后的 <cmd> 参数,会替换掉前面 Dockerfile 文件中的 CMD ["catalina.sh", "run"] 命令中的参数。因此当容器启动后,运行的将是 bash 而不是启动 Tomcat 服务。
CMD 与 ENTRYPOINT 一起使用时会将 CMD 的内容作为参数传递给 ENTRYPOINT:
FROM nginx
ENTRYPOINT ["nginx", "-c"]
CMD ["/etc/nginx/nginx.conf"]
如上配置,当运行容器的时候,相当于执行了指令 nginx -c /etc/nginx/nginx.conf
如果想要在启动容器的时候,覆盖 /etc/nginx/nginx.conf,使用一个新的配置文件。那么可以在启动容器的时候指定 <cmd> 参数:
docker run -it liwy-nginx -c /etc/nginx/new.conf
最终相当于执行了指令 nginx -c /etc/nginx/new.conf
四、Dockerfile 示例
下面我们将构建一个我们自己的 tomcat 镜像:
1. 下载 tomcat 安装包 apache-tomcat-10.1.25.tar.gz
2. 同一目录下创建 Dockerfile 脚本文件
# 设置基础镜像为 Ubuntu 22.04
FROM ubuntu:22.04
# 设置工作目录
WORKDIR /opt
# 设置环境变量,防止在安装时有提示
ENV TZ=Asia/Shanghai
ENV DEBIAN_FRONTEND=noninteractive
# 更新软件包列表
RUN apt update \
# 安装jdk
&& apt install -y openjdk-17-jdk-headless \
# 安装软件包之后清理APT缓存
&& rm -rf /var/lib/apt/lists/*
# 使用 ADD 命令拷贝并解压 Tomcat 压缩包
ADD apache-tomcat-10.1.25.tar.gz /opt/
# 重命名解压后的目录
RUN mv apache-tomcat-10.1.25 tomcat
# 暴露 Tomcat 默认的端口
EXPOSE 8080
# 启动 Tomcat
CMD ["/opt/tomcat/bin/catalina.sh", "run"]
3. 最后构建镜像
docker build -t liwy-tomcat:10.1.25 .