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

发布于:2025-07-14 ⋅ 阅读:(14) ⋅ 点赞:(0)

一. Docker 镜像管理

Docker 镜像除了是 Docker 的核心技术之外,也是应用发布的标准格式。一个完整的 Docker 镜像可以支撑一个 Docker 容器的运行,在 Docker 的整个使用过程中,进入一个已经定型的容器之后,就可以在容器中进行操作,最常见的操作就是在容器中安装应用服务。 如果要把已经安装的服务进行迁移,就需要把环境以及搭建的服务生成新的镜像

1. Docker 镜像结构

镜像不是一个单一的文件,而是有多层构成。可以通过 docker history 命令查看镜像中各层内容及大小,每层对应着Dockerfile中的一条指令。Docker 镜像默认存储在/var/lib/docker/目录中。容器其实是在镜像的最上面加了一层读写层, 在运行容器里做的任何文件改动,都会写到这个读写层。如果删除了容器,也就删除了其最上面的读写层,文件改动也就丢失了。Docker 使用存储驱动管理镜像每层内容及可读写层的容器层。Docker 镜像是分层的,下面这些知识点非常重要

  • Dockerfile 中的每个指令都会创建一个新的镜像层

  • 镜像层将被缓存和复用

  • 当 Dockerfile 的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效

  • 某一层的镜像缓存失效,它之后的镜像层缓存都会失效

  • 镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,只是这个文件在 Docker 容器中不可见了

2. Dockerfile 介绍

Dockfile 是一种被 Docker 程序解释的脚本,Dockerfile 由多条的指令组成,每条指令对应Linux 下面的一条命令。Docker 程序将这些 Dockerfile 指令翻译成真正的 Linux 命令。Dockerfile有自己书写格式和支持的命令,Docker 程序解决这些命令间的依赖关系,类似于Makefile。Docker 程序将读取 Dockerfile,根据指令生成定制的镜像。相比镜像这种黑盒子,Dockerfile 这种显而易见的脚本更容易被使用者接受,它明确的表明镜像是怎么产生的。有了 Dockerfile,当有定制额外的需求时,只需在 Dockerfile 上添加或者修改指令, 重新生成镜像

二. Dockerfile 语法基础

Dockerf其中包含系列用于构建DocKer镜像的指令。通过编写Dockerfile,可以自动化地创建自定义的 Docker 镜像。以下为你详细介绍 Dockerfile 的常用语法:

1. 基础指令

(1)FROM

指定基础镜像,所有的 Dockerfile 都必须以 FROM 指令开头,它定义了新镜像基于哪个基础镜像构建

示例:基于 Ubuntu 20.04 镜像构建新镜像
FROM ubuntu:20.04

(2)MAINTAINER (已弃用,推荐使用 LABEL)

用于指定镜像的维护者信息。不过在较新的Docker版本中,推荐使用 LABEL 指令来替代

示例:
MAINTAINER John Doe <johndoe@example.com>

(3)LABEL

为镜像添加元数据,这些元数据可以是任何信息,如作者、版本、描述等,方便对镜像进行管理和识别

示例:
LABEl version="1.0" description="This is a sample image" maintainer="John'

2. 环境设置指令

(1)ENV

设置环境变量,这些环境变量会在容器运行时持续存在,并且可以被容器内的应用程序使用

示例:设置 MySOL的root 用户密码环境变量
ENV MYSOL ROOT PASSWORD=password

(2)ARG

定义在构建镜像时可以传递的参数,这些参数只在镜像构建过程中有效

示例:定义一个名为 VERSION 的参数,默认值为 1.0
ARG VERSION=1.0

3. 文件操作指令

(1)CPOY

将本地文件或目录复制到镜像中

示例:将本地的 app.py 文件复制到镜像的 /app/ 日录下
copy app.py /app/

(2)ADD

与 COPY 类似,也是将文件或目录复制到镜像中,但 ADD 还支持从远程 URL 下载文件和自动解压压缩文件

示例:从指定 URL 下载文件并复制到镜像的 /app/ 目录下a
ADD http://example.com/file.tar.gz /app/

(3)WORKDIR

设置工作目录,后续的 RUN、CMD、ENTRYPOINT、COPY 和 ADD 等指令都会在这个工作目录下执行

示例:将工作目录设置为 /appa
WORKDIR /app

4. 执行命令指令

(1)RUM

在构建镜像的过程中执行命令,常用于安装软件包、配置环境等操作

示例:在镜像中更新软件源并安装Python 3
RUN apt-get update && apt-get install -y python3

(2)CMD

为容器提供默认的执行命令。一个 Dockerfile 中只能有一个 CMD 指令,如果有多个,只有最后个会生效。当使用 dockerrun 启动容器时,如果没有指定其他命令,就会执行 CMD 指定的命令

示例:指定容器启动时默认执行 python3 app.py 命令
CMD ["python3","app.py"]

(3)ENTRYPOINT

配置容器启动时执行的命令,与CMD 类似,但 ENTRYPOINT 的命令不会被 docker run 后面的命令覆盖,而是将 docker run 后面的命令作为参数传递给 ENTRYPOINT 命令

示例::容器启动时会执行 python3 app.py,如果使用 docker run<image>test.py 启动容器,则会执行 python3 test.py
ENTRYPOINT ["python3"]
CMD ["app.py"]

5. 网络和暴露端口指令

(1)EXPOSE

声明容器在运行时会监听的端口,但这只是一个声明,并不会实际进行端口映射。在使用 dockerrun 启动容器时,需要使用-p或-P 选项进行端口映射

示例:声明容器会监听 8080 端口
EXPOSE 8080

6. 容器挂载指令

(1)VOLUME

创建一个可以从本地主机或其他容器挂载的挂载点,用于持久化数据或共享数据

示例:创建一个名为 /app/data 的挂载点
VOLUME ["/app/data"]

三. Dockerfile 案例实施

1. 案例一:构建nginx容器

(1)拉取 centos 镜像

在这里插入图片描述
在这里插入图片描述

(2)创建dockerfile 工作目录

[root@localhost ~]# mkdir nginx
[root@localhost ~]# cd nginx/

在这里插入图片描述

(3)创建 dockerfile

[root@localhost nginx]# vim 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 makecache
RUN yum -y install gcc zilb-devel pcre-devel openssl-devel make
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
EXPOSE 443
ADD run.sh /run.sh
RUN chmod +x /run.sh
CMD ["/run.sh"]

在这里插入图片描述

(4)编写 nginx 启动脚本

[root@localhost nginx]# vim run.sh

在这里插入图片描述

(5)用 dockerfile 创建镜像

[root@localhost nginx]# docker build -t mynginx .

在这里插入图片描述

(6)启动容器并创建测试文件

[root@localhost nginx]# docker run -dit -p 8080:80 -v /www/html:/web  -v /root/nginx/nginx.conf:/usr/local/nginx/conf/nginx.conf --name nginx01 mynginx
[root@localhost nginx]# cd /www/html/
[root@localhost html]# echo "this is my nginx" > index.html

在这里插入图片描述

(7)编辑 nginx.conf 文件

在这里插入图片描述

(8)访问nginx网站

浏览器访问:http://192.168.10.101:8080

在这里插入图片描述

2. 案例二:构建Tomcat容器

(1)创建工作目录

[root@localhost ~]# mkdir tomcat
[root@localhost ~]# cd tomcat/

在这里插入图片描述

(2)创建 dockerfile 文件

[root@localhost tomcat]# vim dockerfile 
FROM centos:7
ADD apache-tomcat-8.5.16.tar.gz /usr/local/
ADD jdk-8u91-linux-x64.tar.gz /usr/local/

RUN mv /usr/local/apache-tomcat-8.5.16 /usr/local/tomcat
RUN mv /usr/local/jdk1.8.0_91  /usr/local/java

ENV JAVA_HOME /usr/local/java
ENV JAVA_BIN /usr/local/java/bin
ENV JRE_HOME /usr/local/java/jre
ENV PATH $PATH:/usr/local/java/bin:/usr/local/java/jre/bin
ENV CLASSPATH $CLASSPATH:/usr/local/java/lib:/usr/local/java/jre/lib

EXPOSE 8080

ADD run.sh /run.sh
RUN chmod +x /run.sh
CMD ["/run.sh"]

在这里插入图片描述

(3)创建启动脚本

[root@localhost tomcat]# vim run.sh

在这里插入图片描述

(4)用 dockerfile 生成镜像

[root@localhost tomcat]# docker build -t mytomcat .

在这里插入图片描述

(5)启动容器

[root@localhost tomcat]# docker run -dit -p 8081:8080 --name tomcat01 mytomcat

在这里插入图片描述

(6)访问 tomcat 网站

浏览器访问:http://192.168.10.101:8081

在这里插入图片描述

3. 案例三:构建mysql容器

(1)创建工作目录

[root@localhost ~]# mkdir mysql
[root@localhost ~]# cd mysql/

在这里插入图片描述

(2)创建 dockerfile 文件

[root@localhost mysql]# vim 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 makecache
RUN yum -y install mariadb mariadb-server
RUN chown -R mysql:mysql /var/lib/mysql
ADD run.sh /run.sh
RUN chmod +x /run.sh
RUN /run.sh
EXPOSE 3306
CMD ["mysqld_safe"]

在这里插入图片描述

(3)编写 mysql 初始化脚本

[root@localhost mysql]# vim run.sh
#!/bin/bash
mysql_install_db --user=mysql
sleep 3
mysqld_safe &
sleep 3

mysqladmin -u root password "pwd123"

mysql -uroot -ppwd123 -e "grant all privileges on *.* to 'root'@'%' identified by 'pwd123';"

mysql -uroot -ppwd123 -e "grant all privileges on *.* to 'localhost'@'%' identified by 'pwd123';"

mysql -uroot -ppwd123 -e "flush privileges;"

在这里插入图片描述

(4)生成镜像

[root@localhost mysql]# docker build -t mymysql .

在这里插入图片描述

(5)创建容器

[root@localhost mysql]# docker run -dit -p 3306:3306 mymysql
[root@localhost mysql]# dnf -y install mysql

在这里插入图片描述

(6)测试访问mysql

[root@localhost mysql]# mysql -uroot -ppwd123 -h192.168.10.101 -P3306

在这里插入图片描述

4. 案例四:构建php容器

(1)创建工作目录

[root@localhost ~]# mkdir php
[root@localhost ~]# cd php/

在这里插入图片描述

(2)创建 dockerfile(yum 安装安装)

[root@localhost php]# vim dockerfile
FROM centos:7
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 curl -o /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
RUN yum clean all
RUN yum makecache
RUN yum install -y wget net-tools php php-fpm php-common php-devel php-mysql
RUN sed -i 's/127.0.0.1/0.0.0.0/g' /etc/php-fpm.d/www.conf
RUN sed -i 's/listen.allowed_clients/;listen.allowed_clients/g' /etc/php-fpm.d/www.conf
RUN sed -i 's/;default_charset/default_charset/g' /etc/php.ini
EXPOSE 9000
CMD ["php-fpm"]

在这里插入图片描述

(3)生成镜像

[root@localhost php]# docker build -t myphp .

在这里插入图片描述

(4)启动容器

[root@localhost php]# docker run -id --net=my_net -v /web:/web --name php01 myphp

(5)测试

cd /web
 
vim aaa.php
###编辑内容###
<?php
phpinfo();
?>
 
vim bbb.php
###编辑内容###
<?php
$link=mysqli_connect('mysql01','root','123456');
if($link) echo "test OK";
mysqli_close($link);
?>

在这里插入图片描述

在这里插入图片描述

四. Dockerfile 语法注意事项

在编写 Dockerfile 时,掌握基础语法的注意事项能够帮助你构建出高效、可靠且易于维护的Docker 镜像。以下是一些关键的注意事项:

1. 指令书写规范

(1)大小写

Dockerfile 中的指令不区分大小写,但建议使用大写,以增强可读性。例如,使用 FROM、RUN 而丰from、 run

(2)顺序

指令的顺序非常重要,因为 Docker 会按顺序依次执行这些指令。合理安排指令顺序有助于提高构建效率和镜像的可维护性。例如,将不常变动的指令放在前面,充分利用 Docker 构建缓存机制

(3)注释

可以使用 #来添加注释,这有助于解释 Dockerfile 中各部分的作用,提高代码的可读性

2. 基础镜像选择

(1)稳定性与安全性

选择稳定、官方且维护良好的基础镜像,这样能保证镜像的安全性和可靠性。例如,官方的 ubuntu、alpine 等镜像都有较好的维护和更新机制

(2)镜像大小
如果对镜像大小有严格要求,可选择轻量级的基础镜像,如 alpine 镜像,它体积小巧,适合构建资源占用少的容器

3. 文件操作注意

(1)COPY 与 ADD 的区别

COPY 仅用于简单的文件和目录复制,语法清晰,性能较好,推荐优先使用

ADD 除复制功能外,还支持从 URL 下载文件和自动解压压缩文件,但功能复杂可能带来安全风险和不可预测性,所以仅在确实需要这些额外功能时使用

(2)文件路径

使用相对路径时要确保路径在构建上下文中是正确的.构建上下文是指执行 docker build 命令时指定的目录,只有该目录下的文件和子目录才能被复制到镜像中

4. 执行命令要点

(1)RUN 命令优化

尽量将多个相关的命令合并成一个 RUN 指令,减少镜像的层数,从而减小镜像体积。例如,使用&& 连接多个命令

(2)清理临时文件和缓存

要及时清理临时文件和缓存,避免将不必要的文件包含在镜像中。如上述示例中使用rm-rf/var/lib/apt/lists/* 清理 APT 缓存

(3)CMD与 ENTRYPOINT 搭配

  • CMD 为容器提供默认执行命令,ENTRYPOINT配置容器启动时执行的命令。当两者搭配使用时CMD 通常作为 ENTRYPOINT 的默认参数

例如:

ENTRYPOINT [“python3”]

CMD [“app.py”]

  • 若在 docker run 时指定了命令,CMD 的内容会被覆盖,而 ENTRYPOINT 的命令不会被覆盖,指定的命令会作为参数传递给 ENTRYPOINT。

5. 环境变量和参数设置

(1)ENV 与 ARG 的区别

ENV 设置的环境变量在容器运行时持续存在,可被容器内的应用程序使用

ARG 定义的参数仅在镜像构建过程中有效,用于传递构建时的参数

(2)安全性

避免在 ENV 或 ARG 中设置敏感信息(如密码、密钥等),若确实需要,可以在运行容器时通过环境变量传递

(3)网络和端口声明

EXPOSE 指令:EXPOSE 只是声明容器监听的端口,不会进行实际的端口映射。在使用 docker run 启动容器时,需使用-p或-P 选项进行端口映射

6. 缓存利用与清理

(1)缓存机制

Docker 构建镜像时会利用缓存,若某条指令的内容未发生变化,会直接使用之前的缓存结果,加快构建速度.因此,将不常变动的指令放在前面,可充分利用缓存

(2)缓存清理

当需要强制重新构建镜像、不使用缓存时,可使用 docker build --no-cache 命令


网站公告

今日签到

点亮在社区的每一天
去签到