Dockerfile 配置和常用命令
Dockerfile 配置和常用命令
Dockerfile 是一个文本文件,包含了一系列用于构建 Docker 镜像的指令。通过 Dockerfile,我们可以自动化地构建出包含应用程序及其运行环境的镜像。
基本结构
Dockerfile 的基本结构如下:
- 基础镜像定义
- 元数据信息
- 镜像构建指令
- 容器启动命令
Dockerfile 配置项
1. FROM
指定基础镜像: FROM <image>[:<tag>] [AS <name>]
必须是 Dockerfile 的第一条指令(注释除外)
推荐使用官方镜像作为基础镜像
尽量使用特定版本标签,而不是 latest
FROM ubuntu:20.04
# 或
FROM mysql:8.0
2. LABEL
添加元数据信息: LABEL <key>=<value> <key>=<value> ...
用于为镜像添加元数据
可以替代已弃用的 MAINTAINER 指令
LABEL maintainer="your-email@example.com"
LABEL version="1.0"
LABEL description="MySQL 8.0 with custom configuration"
3. ENV
设置环境变量: ENV <key> <value> 、 ENV <key>=<value>
设置的环境变量在构建过程和容器运行时都可用
可用于配置应用程序参数
ENV MYSQL_ROOT_PASSWORD=secret
ENV MYSQL_DATABASE=myapp
ENV MYSQL_USER=myuser
ENV MYSQL_PASSWORD=mypassword
4. RUN
执行命令: RUN <command> (shell 格式)、RUN ["executable", "param1", "param2"] (exec 格式)
每条 RUN 指令都会在当前镜像之上创建一个新层
多个命令应尽量合并到一条 RUN 指令中,减少镜像层数
RUN apt-get update && apt-get install -y \
package1 \
package2 \
&& rm -rf /var/lib/apt/lists/*
5. COPY
复制文件: COPY [--chown=<user>:<group>] <src>... <dest>、COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
从构建上下文复制文件到镜像中
源路径可以是文件或目录
目标路径可以是绝对路径或相对于 WORKDIR 的路径
默认情况下,COPY 命令会保持源文件的权限,但可以通过 --chown 参数来修改权限
COPY ./my.cnf /etc/mysql/conf.d/
COPY ./init.sql /docker-entrypoint-initdb.d/
6. ADD
高级复制 : ADD [--chown=<user>:<group>] <src>... <dest>
ADD 命令与 COPY 命令类似,但 ADD 命令支持更丰富的功能,如:
- 源路径可以是文件或目录
- 源路径可以是 URL
- 源路径可以是 tar 文件
- 源路径可以是 gzip 压缩文件
除非需要 ADD 的特殊功能,否则推荐使用 COPY
# 1. 添加本地文件到镜像
ADD app.jar /app/app.jar
# 2. 添加并重命名文件
ADD config.properties /app/config/app.properties
# 3. 添加整个目录
ADD src /app/src
# 4. 使用URL添加文件
ADD https://example.com/file.tar.gz /tmp/
# 5. 自动解压压缩文件(tar、gzip、bzip2等)
ADD archive.tar.gz /tmp/
# 6. 设置文件所有权
ADD files/ /app/data/
# 7. 使用通配符添加多个文件
ADD *.txt /app/texts/
# 8. 添加文件并保持文件夹结构
ADD config/ /app/config/
7. WORKDIR
指定工作目录 :WORKDIR /path/to/workdir
设置后续指令的工作目录
如果目录不存在,会自动创建
可以多次使用,路径可以是相对路径(相对于前一个 WORKDIR)
WORKDIR /app
8. EXPOSE
暴露端口 :EXPOSE <port> [<port>/<protocol>...]
声明容器运行时监听的端口
不会自动映射到宿主机,需要在运行容器时使用 -p 参数
EXPOSE 3306
EXPOSE 33060
EXPOSE 8080/tcp
EXPOSE 8080/udp
EXPOSE 8080/tcp 8080/udp
EXPOSE 8080-8085
EXPOSE 8080-8085/tcp
EXPOSE 8080-8085/udp
EXPOSE 8080-8085/tcp 8080-8085/udp
9. VOLUME
挂载卷 :VOLUME ["<路径1>", "<路径2>", ...] 、VOLUME <路径>
创建一个具有指定名称的挂载点
用于持久化数据和共享数据
不需要在 Dockerfile 中使用 VOLUME 指令时指定宿主机目录。VOLUME 指令只是在镜像中声明挂载点,具体的宿主机目录是在运行时决定的。
# 创建单个挂载点
VOLUME /data
# 创建多个挂载点(JSON数组格式)
VOLUME ["/var/www/html", "/var/log/nginx", "/database"]
10. USER
设置用户: SER <user>[:<group>]、USER <UID>[:<GID>]
设置运行后续指令的用户和用户组
可以提高安全性,避免以 root 用户运行应用程序
USER mysql
11. ARG
构建参数 ARG <name>[=<default value>]
定义构建时使用的变量
可以使用
--build-arg <varname>=<value>在构建时传递
ARG MYSQL_VERSION=8.0
FROM mysql:${MYSQL_VERSION}
12. CMD
容器启动命令 CMD ["executable","param1","param2"] (exec 格式,推荐)、CMD command param1 param2 (shell 格式)
指定容器启动时执行的命令
Dockerfile 中只能有一条 CMD 指令,如果有多条,只有最后一条生效
会 被 docker run 后面的命令覆盖
CMD ["echo","hello world"]
CMD echo "hello world"
CMD ["mysqld"]
13. ENTRYPOINT
容器启动入口点: ENTRYPOINT ["executable", "param1", "param2"] 、 ENTRYPOINT command param1 param2
配置容器作为一个可执行文件运行
不会 被 docker run 后面的命令覆盖,而是会追加
通常与 CMD 一起使用,ENTRYPOINT 指定命令,CMD 指定参数
# 固定入口点
ENTRYPOINT ["mysql"]
# 默认连接参数
CMD ["-h", "localhost", "-u", "root", "-p"]
14. HEALTHCHECK
健康检查:HEALTHCHECK [OPTIONS] CMD command 、 HEALTHCHECK NONE
告诉 Docker 如何测试容器是否仍在工作
可以检测应用程序是否仍在运行而不仅仅是进程是否存在
HEALTHCHECK \
CMD mysqladmin ping -h localhost || exit 1
# 检查间隔30s,命令超时时间30s,延迟5s启动健康检查,失败重试3次,如果mysqladmin ping -h localhost失败,则返回1,否则返回0
15. ONBUILD
延迟执行指令:ONBUILD <INSTRUCTION>
当本镜像被用作其他镜像的基础镜像时,会触发执行
用于创建需要自定义的镜像
ONBUILD COPY . /app/src
ONBUILD RUN make /app/src
16. STOPSIGNAL
设置容器停止信号:STOPSIGNAL <SIGNAL>
- 设置发送给容器以停止容器的系统调用信号
STOPSIGNAL SIGTERM
17. SHELL
设置命令执行时使用的默认 shell:SHELL ["executable", "parameters"]
- 覆盖用于命令的 shell 格式的默认 shell
SHELL ["/bin/bash", "-c"]
使用示例(部署 Mysql)
- 创建 Dockerfile 文件
# 使用官方 MySQL 镜像作为基础镜像
FROM mysql:8.0
# 设置元数据
LABEL maintainer="admin@example.com"
LABEL version="1.0"
LABEL description="Custom MySQL 8.0 with preconfigured database"
# 设置环境变量(可在运行时覆盖)
ENV MYSQL_ROOT_PASSWORD=default_root_password
ENV MYSQL_DATABASE=myapp_db
ENV MYSQL_USER=myapp_user
ENV MYSQL_PASSWORD=default_user_password
ENV TZ=UTC
# 设置构建参数
ARG DEBIAN_FRONTEND=noninteractive
# 设置工作目录
WORKDIR /tmp
# 复制自定义配置文件
COPY ./config/my.cnf /etc/mysql/conf.d/
COPY ./scripts/init.sql /docker-entrypoint-initdb.d/
# 复制健康检查脚本
COPY ./scripts/healthcheck.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/healthcheck.sh
# 安装额外的软件包(如果需要)
RUN apt-get update && \
apt-get install -y --no-install-recommends \
tzdata \
&& rm -rf /var/lib/apt/lists/*
# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 创建数据目录并设置权限
RUN mkdir -p /var/lib/mysql && \
chown -R mysql:mysql /var/lib/mysql
# 暴露 MySQL 默认端口
EXPOSE 3306
EXPOSE 33060
# 设置数据卷
VOLUME /var/lib/mysql
# 设置健康检查
HEALTHCHECK \
CMD /usr/local/bin/healthcheck.sh
# 使用官方镜像的入口点
ENTRYPOINT ["docker-entrypoint.sh"]
# 设置默认启动命令
CMD ["mysqld"]
- Mysql 配置文件
- 创建
config/my.cnf的配置文件,并添加以下内容:
[mysqld]
max_connections = 500
innodb_buffer_pool_size = 512M
default-authentication-plugin=mysql_native_password
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
scripts/init.sql- 初始化数据库脚本
-- 创建额外的数据库
CREATE DATABASE IF NOT EXISTS additional_db;
-- 创建额外的用户和权限
CREATE USER IF NOT EXISTS 'additional_user'@'%' IDENTIFIED BY 'additional_password';
GRANT ALL PRIVILEGES ON additional_db.* TO 'additional_user'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
scripts/healthcheck.sh- 健康检查脚本:
#!/bin/bash
# 检查 MySQL 服务是否正常运行
mysqladmin ping -h localhost -u root -p${MYSQL_ROOT_PASSWORD} 2>/dev/null || exit 1
- 构建和运行
- 构建镜像
# 在 Dockerfile 所在目录执行
docker build -t my-custom-mysql:1.0 .
# 使用构建参数
docker build --build-arg MYSQL_VERSION=8.0 -t my-custom-mysql:1.0 .
- 运行容器
# 基本运行
docker run -d \
--name mysql-container \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-e MYSQL_DATABASE=myapp \
-e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=mypassword \
-p 3306:3306 \
my-custom-mysql:1.0
# 使用数据卷持久化数据
docker run -d \
--name mysql-container \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-v mysql_data:/var/lib/mysql \
-p 3306:3306 \
my-custom-mysql:1.0
# 使用自定义配置文件
docker run -d \
--name mysql-container \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-v /path/to/custom/my.cnf:/etc/mysql/conf.d/my.cnf \
-v mysql_data:/var/lib/mysql \
-p 3306:3306 \
my-custom-mysql:1.0
- 管理容器
# 查看容器日志
docker logs mysql-container
# 查看容器状态
docker ps -a
# 进入容器
docker exec -it mysql-container mysql -u root -p
# 停止容器
docker stop mysql-container
# 启动容器
docker start mysql-container
# 删除容器
docker rm mysql-container
# 删除镜像
docker rmi my-custom-mysql:1.0