一、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 编写规范(补充知识点)
- 指令大写:提高可读性,如 FROM、RUN、COPY
- 顺序优化:不常变的指令放前面,最大化利用缓存
- 减少层数:多条 RUN 合并,清理 yum/apt 缓存
- 安全规范:不在 Dockerfile 写明文密码,用运行时环境变量传入
- 最小镜像:优先用 Alpine 基础镜像,体积小、漏洞少
六、常用构建与排查命令(补充)
bash
运行
# 不使用缓存构建
docker build --no-cache -t myimg .
# 查看镜像分层
docker history mynginx
# 进入容器排查
docker exec -it 容器ID /bin/bash
# 查看容器日志
docker logs 容器ID