四时宝库

程序员的知识宝库

Docker 备忘录 - 06. Dockerfile 构建镜像

一、编写 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 .

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接