Docker 高级管理 ——Dockerfile 镜像制作

一、Docker 镜像核心原理(补充知识点)

1. 镜像分层机制

Docker 镜像不是单一文件,而是多层只读层叠加而成:

  • 每一层对应 Dockerfile 中一条指令 ,可通过 docker history <镜像名> 查看
  • 镜像层不可修改,修改只能新增一层
  • 层会被缓存复用,指令不变则直接用缓存,大幅提速
  • 某一层缓存失效,其后所有层缓存全部失效
  • 容器 = 镜像只读层 + 顶部读写层,文件修改只存在于读写层,删容器即丢失

2. 镜像存储位置

默认路径:/var/lib/docker/<存储驱动>/主流存储驱动:overlay2(生产推荐)、aufs、devicemapper


二、Dockerfile 基础认知

1. 定义

Dockerfile 是被 Docker 引擎解析的构建脚本,由指令集合组成,自动生成自定义镜像。

2. 优势

  • 透明:看得见构建过程,不是黑盒镜像
  • 可复现:改几行就能重新构建
  • 易维护:适合团队协作、CI/CD 流水线

三、Dockerfile 指令全解(含原文 + 补充)

1. 基础指令

FROM(必须首行)

指定基础镜像,所有 Dockerfile必须以 FROM 开头

dockerfile

复制代码
FROM centos:7
FROM ubuntu:20.04
FROM alpine:3.18

补充知识点:优先用官方镜像、带版本标签,不用 latest 避免不稳定。

LABEL(替代 MAINTAINER)

添加镜像元数据(作者、版本、描述)。

dockerfile

复制代码
LABEL version="1.0"
LABEL description="自定义Nginx镜像"
LABEL maintainer="dev@example.com"

2. 环境指令

ENV

设置容器运行时生效的环境变量,永久生效。

dockerfile

复制代码
ENV MYSQL_ROOT_PASSWORD=123456
ENV JAVA_HOME=/usr/local/jdk1.8.0_91
ENV PATH=$PATH:$JAVA_HOME/bin
ARG

设置仅构建时生效的参数,容器运行时不存在。

dockerfile

复制代码
ARG VERSION=1.19.5
ARG USER=root

补充知识点 :构建时可覆盖 docker build --build-arg VERSION=1.21.0 -t mynginx .

3. 文件操作指令

COPY

复制本地文件 / 目录 到镜像,推荐优先使用

dockerfile

复制代码
COPY app.py /app/
COPY nginx.conf /etc/nginx/
ADD

比 COPY 更强:支持URL 下载自动解压压缩包

dockerfile

复制代码
ADD nginx-1.19.5.tar.gz /opt/
ADD http://example.com/file.tar.gz /app/

补充知识点:单纯复制用 COPY,需要解压 / 下载才用 ADD。

WORKDIR

设置工作目录,自动创建,后续指令都在此目录执行。

dockerfile

复制代码
WORKDIR /opt/nginx-1.19.5

4. 执行命令指令

RUN

构建镜像时执行,用于安装软件、配置环境。

dockerfile

复制代码
RUN yum install -y gcc make openssl-devel
RUN ./configure --prefix=/usr/local/nginx && make && make install

补充知识点 :多条命令用&&合并,减少镜像层数、缩小体积。

CMD

容器启动默认命令 ,只能有一个,最后一个生效,可被docker run覆盖。

dockerfile

复制代码
CMD ["python3","app.py"]
CMD ["/run.sh"]
ENTRYPOINT

容器启动入口命令 ,不会被docker run覆盖,run 后面的内容会作为参数传入。

dockerfile

复制代码
ENTRYPOINT ["python3"]
CMD ["app.py"]
# 执行:python3 app.py

5. 网络与挂载指令

EXPOSE

声明容器暴露端口,仅声明,不映射

dockerfile

复制代码
EXPOSE 80
EXPOSE 443
EXPOSE 8080
EXPOSE 3306

补充知识点 :映射需用-p 主机端口:容器端口

VOLUME

声明数据卷,实现数据持久化。

dockerfile

复制代码
VOLUME ["/app/data"]
VOLUME ["/var/lib/mysql"]

四、完整实战案例(原文所有代码 + 详细步骤)

案例 1:构建 Nginx 镜像

1)准备环境

bash

运行

复制代码
docker pull centos:7
mkdir -p /opt/nginx
cd /opt/nginx
2)编写 Dockerfile

dockerfile

复制代码
FROM centos:7
RUN rm -rf /etc/yum.repos.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum clean all
RUN yum -y install pcre-devel zlib-devel gcc make openssl-devel
ADD nginx-1.19.5.tar.gz /opt
WORKDIR /opt/nginx-1.19.5
RUN ./configure --prefix=/usr/local/nginx && make && make install
ADD nginx.conf /usr/local/nginx/conf/nginx.conf
EXPOSE 80 443
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
3)启动脚本 run.sh

bash

运行

复制代码
#!/bin/bash
/usr/local/nginx/sbin/nginx
4)构建镜像

bash

运行

复制代码
docker build -t mynginx .
5)启动容器

bash

运行

复制代码
# 基础启动
docker run -d --name nginx01 -p 8080:80 mynginx

# 挂载目录
docker run -d --name nginx02 -p 8081:80 -v /www/html:/usr/local/nginx/html mynginx

案例 2:构建 Tomcat 镜像

Dockerfile

dockerfile

复制代码
FROM centos:7
ADD jdk-8u91-linux-x64.tar.gz /usr/local/
ENV JAVA_HOME=/usr/local/jdk1.8.0_91
ENV PATH=$PATH:$JAVA_HOME/bin
ADD apache-tomcat-8.5.16.tar.gz /
RUN mv /apache-tomcat-8.5.16 /usr/local/tomcat
EXPOSE 8080
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
run.sh

bash

运行

复制代码
#!/bin/bash
/usr/local/tomcat/bin/startup.sh
tail -f /dev/null
构建运行

bash

运行

复制代码
docker build -t mytomcat .
docker run -d --name tomcat01 -p 8080:8080 mytomcat

案例 3:构建 MySQL(MariaDB)镜像

Dockerfile

dockerfile

复制代码
FROM centos:7
RUN rm -rf /etc/yum.repos.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum clean all
RUN yum -y install mariadb mariadb-server
RUN chown -R mysql:mysql /var/lib/mysql
ADD init.sh /init.sh
RUN chmod 755 /init.sh
RUN /init.sh
EXPOSE 3306
CMD ["mysqld_safe"]
init.sh

bash

运行

复制代码
#!/bin/bash
mysql_install_db --user=mysql
sleep 3
mysqld_safe &
sleep 3
mysqladmin -u root password '123456'
mysql -uroot -p123456 -e "grant all on *.* to 'root'@'%' identified by '123456';"
mysql -uroot -p123456 -e "flush privileges;"
构建运行

bash

运行

复制代码
docker build -t mysql .
docker run -d --name mysql01 -p 3306:3306 mysql

案例 4:构建 PHP 镜像

Dockerfile

dockerfile

复制代码
FROM centos:7
LABEL maintainer="jacker"
RUN rm -rf /etc/yum.repos.d/*
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum clean all
RUN yum install epel-release -y
RUN yum install -y php php-fpm php-mysqlnd
EXPOSE 9000
CMD ["php-fpm"]
构建运行

bash

运行

复制代码
docker build -t myphp .
docker run -d --name php01 -p 9000:9000 myphp

五、Dockerfile 编写规范(补充知识点)

  1. 指令大写:提高可读性,如 FROM、RUN、COPY
  2. 顺序优化:不常变的指令放前面,最大化利用缓存
  3. 减少层数:多条 RUN 合并,清理 yum/apt 缓存
  4. 安全规范:不在 Dockerfile 写明文密码,用运行时环境变量传入
  5. 最小镜像:优先用 Alpine 基础镜像,体积小、漏洞少

六、常用构建与排查命令(补充)

bash

运行

复制代码
# 不使用缓存构建
docker build --no-cache -t myimg .

# 查看镜像分层
docker history mynginx

# 进入容器排查
docker exec -it 容器ID /bin/bash

# 查看容器日志
docker logs 容器ID
相关推荐
STAT abil1 小时前
docker离线安装及部署各类中间件(x86系统架构)
docker·中间件·系统架构
极客先躯1 小时前
高级java每日一道面试题-2025年12月06日-实战篇[Dockerj]-如何配置 Docker 的镜像加速器?国内有哪些常用加速源?
java·docker·配置docker的镜像加速器·国内有哪些常用加速源·镜像加速器的本质与配置原理·镜像拉取流程对比·加速前后架构差异
kiku18181 小时前
Docker高级管理--Dockerfile镜像制作
java·docker·eureka
bukeyiwanshui2 小时前
20260509 Dockerfile案例
linux·运维·docker
岳来2 小时前
docker 容器重启策略RestartPolicy
运维·docker·容器·restartpolicy
小黑蛋学java4 小时前
Ubuntu Docker 安装手册
linux·ubuntu·docker
qq_3643717216 小时前
基于 Docker 容器化环境配置
运维·docker·容器
GentleDevin17 小时前
Docker 运维常用命令大全
docker·容器·运维命令
运维全栈笔记17 小时前
基于Docker的MinIO单机部署与功能测试指南
运维·docker·容器