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
相关推荐
专业白嫖怪2 小时前
什么是docker
运维·docker·容器
qq_452396237 小时前
第十篇:《Dockerfile 最佳实践与镜像瘦身》
docker
Plastic garden7 小时前
Docker(1)
运维·docker·容器
gs801408 小时前
网络隐形杀手:从 Could not connect to SMTP host 报错深度剖析 Docker MTU 黑洞理论与实战
网络·docker·容器
程序猿阿伟9 小时前
《一套完整方法论:搞定图形应用的Docker镜像优化》
数据库·docker·容器
java_logo9 小时前
2026 Docker 国内镜像加速配置教程
运维·docker·容器·docker镜像·docker镜像源·docker镜像加速·docker镜像国内库
IT策士10 小时前
Docker从0到1再到 Kubernetes 实战:第15篇Compose 中的服务依赖、健康检查与启动顺序
docker·容器·kubernetes
“码”力全开10 小时前
深度解析:基于 Docker 与边缘计算的 AI 视频管理平台架构——打通 GB28181/RTSP 协议与“源码交付”的高效集成方案
人工智能·docker·边缘计算
顾默@11 小时前
双系统Ubuntu18.04升级22.04,安装docker进行openclaw安装
运维·docker·容器
木卫二号Coding11 小时前
打包容器有两种方式
docker