使用Dockerfile创建镜像过程

 更新时间:2025年07月24日 10:56:47   作者:LKAI.  
本文介绍Docker安装及镜像分类,详解Dockerfile指令如FROM、RUN、CMD等,涵盖制作镜像步骤与优化技巧,如减少分层和清理数据,适用于自定义镜像构建实践

实验环境

安装好Docker服务

一、容器镜像分类

1、操作系统类

CentOS、Ubuntu

在dockerhub下载或自行制作

示例:把操作系统的文件系统打包生成镜像

1)开启最小化安装的CentOS

2)打包制作CentOS镜像

tar --numeric-owner --exclude=/proc --exclude=/sys -cvf centos7.tar /

  • --numeric-owner:以数字形式保存文件的所有者和组信息,而不是名称。这在跨系统打包时非常有用。
  • --exclude=/proc:排除 /proc 目录。/proc 是一个虚拟文件系统,包含系统运行时的进程信息,不适合打包。
  • --exclude=/sys:排除 /sys 目录。/sys 是另一个虚拟文件系统,包含内核和设备的运行时信息,也不适合打包。
  • -c:创建新的归档文件。
  • -v:显示详细输出,列出正在处理的文件。
  • -f centos7.tar:指定归档文件名为 centos7.tar。
  • /:指定要打包的根目录

3)导入制作的镜像

docker import centos7.tar centos7:v1

cat centos7.tar | docker import - centos7:v1
docker images

4)使用制作的镜像开启容器

docker run -it centos7:v1 /bin/bash

yum -y install httpd

启动http服务

/usr/sbin/apachectl

ctrl+p+q

2、应用类

Tomcat、Nginx、MySQL、Redis

下载、制作均可

为满足不同环境需求,我们经常自己制作

二、利用Dockerfile制作镜像

1、Dockerfile介绍

Dockerfile是一种能够被Docker程序解释的脚本

Dockerfile由一条一条的指令组成,并且有自己的书写格式和支持的命令,当需要在容器镜像中指定自己额外的需求时,只需在Dockerfile上添加或修改指令,然后通过docker build生成我们自定义的容器镜像。

2、Dockerfile指令

(1)构建类指令:用于构建image

其指定的操作不会运行在image的容器上执行

如:FROM、MAINTAINER、RUN、ENV、ADD、COPY

(2)设置类指令:用于设置image的属性

其指定的操作将运行image的容器中执行

如:CMD、ENTRYPOINT、USER、EXPOSE、WORKDIR、VOLUME

对应指令说明:

  • FROM            构建新镜像基于的基础镜像(必须为第一条指令)
  • RUN              执行命令,通常用于安装软件或运行脚本
  • COPY             将文件或目录从主机复制到镜像中
  • ADD              类似 COPY,但支持自动解压 tar 文件和从 URL 下载文件
  • ENV               设置环境变量
  • USER             指定运行后续指令的用户
  • EXPOSE         声明容器运行时监听的端口(容器内打开的端口)
  • WORKDIR      设置工作目录,后续指令默认在该目录下执行
  • CMD              指定容器启动时默认执行的命令(可以被 docker run 覆盖)
  • ENTRYPOINT       指定容器启动时默认执行的命令(不会被 docker run 覆盖,但可以追加参数)

3、Dockerfile指令的详细解释

(1)FROM

  • FROM指令用于指定其后构建新镜像所使用的基础镜像。
  • FROM指令必是Dockerfile文件中的首条命令。
  • FROM指令指定的基础image可以是官方远程仓库中的,也可以位于本地仓库,优先本地仓库。

(2)RUN

RUN指令用于在构建镜像中执行命令,有以下两种格式:

shell格式

  • 格式:RUN <命令>
  • 例:RUN echo 'test' > /var/www/html/index.html

exec格式

  • 格式:RUN ["可执行文件", "参数1", "参数2"]
  • 例:RUN ["/bin/bash", "-c", "echo test > /var/www/html/index.html"]

注意:

按优化的角度来讲,当有多条要执行的命令时,不要使用多条RUN,尽量使用&&符号与\符号连接成一行,因为多条RUN命令会让镜像建立多层

例如:

RUN yum install httpd httpd-devel -y
RUN echo test > /var/www/html/index.html

可以改成

RUN yum install httpd httpd-devel -y && echo test > /var/www/html/index.html

或者改成

RUN yum install httpd httpd-devel -y \ && echo test > /var/www/html/index.html

(3)CMD

CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

格式有三种:

CMD ["executable","param1","param2"]

CMD ["param1","param2"]

CMD command param1 param2

每个Dockerfile只能有一条CMD命令,如果指定了多条命令,只有最后一条会被执行;如果用户启动容器时候指定了运行的命令,则会覆盖掉CMD指定的命令。

什么是启动容器时指定运行的命令?

# docker run -d -p 80:80 镜像名 运行的命令

(4)EXPOSE

EXPOSE指令用于指定容器在运行时监听的端口

  • 格式:EXPOSE <port> [<port>...]
  • 例:EXPOSE 80 3306 8080

上述运行的端口还需要使用docker run运行容器时通过-p参数映射到宿主机的端口。

(5)ENV

ENV指令用于指定一个环境变量。

  • 格式:ENV <key> <value> 或者 ENV <key>=<value>
  • 例:ENV JAVA_HOME /usr/local/jdkxxxx/

(6)ADD

ADD指令用于把宿主机上的文件拷贝到镜像中。

  • 格式:ADD <src> <dest>
  • <src>可以是一个本地文件或本地压缩文件,还可以是一个url,如果把<src>写成一个url,那么ADD就类似于wget命令
  • <dest>路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径

(7)COPY

COPY指令与ADD指令类似,但COPY的源文件只能是本地文件或目录

  • 格式:COPY <src> <dest>

(8)ENTRYPOINT

ENTRYPOINT与CMD非常类似

相同点:

  • 一个Dockerfile只写一条,如果写了多条,那么只有最后一条生效,都是容器启动时才运行

不同点:

  • 如果用户启动容器时候指定了运行的命令,ENTRYPOINT不会被运行的命令覆盖,而CMD则会被覆盖。

格式有两种:

ENTRYPOINT      ["executable", "param1", "param2"]
ENTRYPOINT      command param1 param2

(9)VOLUME

VOLUME指令用于把宿主机里的目录与容器里的目录映射指定挂载点,docker宿主机映射的目录为自动生成的。

  • 格式:VOLUME  ["<mountpoint>"]

(10)USER

USER指令设置启动容器的用户,即程序用户

像hadoop需要hadoop用户操作;oracle需要oracle用户操作,可以是用户名或UID

如:

  • USER daemon
  • USER 1001

注意:

如果设置了容器以daemon用户去运行,那么RUN,CMD和ENTRYPOINT都会以这个用户去运行;镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖指定的用户

(11)WORKDIR

WORKDIR指令设置工作目录,类似于cd命令,不建议使用RUN cd /root,建议使用WORKDIR

如:

  • WORKDIR /root

4、Dockerfile基本构成

  • 基础镜像信息                FROM
  • 维护者信息                    MAINTAINER
  • 镜像操作指令                RUN
  • 容器启动时执行指令     CMD

三、Dockerfile生成容器镜像方法

1、使用Dockerfile生成容器镜像步骤

  • 第一步:创建一个文件夹(目录)
  • 第二步:在文件夹(目录)中创建Dockerfile文件及其它文件
  • 第三步:使用docker build命令构建镜像
  • 第四步:使用构建的镜像启动容器

2、使用Dockerfile生成Nginx容器镜像

mkdir nginxdir

cd nginxdir

echo "nginx is running" > index.html

编写Dockerfile文件

vim Dockerfile

添加:

FROM centos:7

MAINTAINER "lkk"

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 -y install wget

RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

RUN yum -y install nginx

ADD index.html /usr/share/nginx/html/

RUN echo "daemon off;" >> /etc/nginx/nginx.conf

EXPOSE 80

CMD /usr/sbin/nginx

生成镜像

docker build -t nginx:v1 .

3、使用Dockerfile生成容器镜像优化

(1)减少镜像分层

Dockerfile中包含多种指令,如果涉及到部署最多使用的算是RUN命令了,使用RUN命令时,不建议每次安装都使用一条单独的RUN命令,可以把能够合并安装指令合并为一条,这样就可以减少镜像分层。

FROM centos:7

MAINTAINER lkk

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 -y install epel-release

RUN yum -y install gcc gcc-c++ make libxml2 libxml2-devel wget

RUN wget http://docs.php.net/distributions/php-5.6.36.tar.gz

RUN tar zxf php-5.6.36.tar.gz

RUN cd php-5.6.36

RUN ./configure --prefix=/usr/local/php

RUN make -j 4

RUN make install

优化如下:

mkdir /root/phpdir
cd /root/phpdir

将php-5.6.27.tar.gz包上传到/root/phpdir/

进入/root/phpdir目录

vim Dockerfile

添加:

FROM centos:7

MAINTAINER lkk

RUN rm -rf /etc/yum.repos.d/* && curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && yum -y install epel-release && yum -y install gcc gcc-c++ make libxml2 libxml2-devel wget

ADD ./php-5.6.27.tar.gz /

RUN cd /php-5.6.27 && ./configure --prefix=/usr/local/php && make -j 4 && make install

-j(表示 job 的数目)参数可以对项目在进行并行编译。

make -j 4,让make 最多允许 4 个编译命令同时执行,这样可以更有效的利用 CPU 资源。在多核 CPU 上,适当的进行并行编译还是可以明显提高编译速度的,但并行的任务不宜太多,一般是以 CPU 的核心数目的两倍为宜

(2)清理无用数据

一次RUN形成新的一层,如果没有在同一层删除,无论文件是否最后删除,都会带到下一层,所以要在每一层清理对应的残留数据,减小镜像大小。

把生成容器镜像过程中部署的应用软件包做删除处理

vim Dockerfile

添加粗体部分内容:

FROM centos:7

MAINTAINER lkk

RUN rm -rf /etc/yum.repos.d/* && curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && yum -y install epel-release && yum -y install gcc gcc-c++ make libxml2 libxml2-devel wget && yum clean all && rm -rf /var/cache/yum/*

ADD ./php-5.6.27.tar.gz /

RUN cd /php-5.6.27 && ./configure --prefix=/usr/local/php && make -j 16 && make install && rm -rf /php*

生成镜像

docker build -t php:v1 .

四、通过Dockerfile方式创建tomcat镜像

1、创建目录准备相关文件

mkdir tomcatdir
cd tomcatdir/
echo "tomcat test page" > index.html

上传jdk-8u91-linux-x64.tar.gz包到tomcatdir目录

2、编辑Dockerfile文件

vim Dockerfile

注意安装版本(粗体部分)

添加:

FROM centos:7
MAINTAINER "lkk"
ENV VERSION=9.0.99
ENV JAVA_HOME=/usr/local/jdk
ENV TOMCAT_HOME=/usr/local/tomcat
ENV PATH=$TOMCAT_HOME/bin:$JAVA_HOME/bin:$PATH
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo && \
    yum -y install wget && \
    wget https://dlcdn.apache.org/tomcat/tomcat-9/v${VERSION}/bin/apache-tomcat-${VERSION}.tar.gz --no-check-certificate && \
    tar xf apache-tomcat-${VERSION}.tar.gz && \
    mv apache-tomcat-${VERSION} /usr/local/tomcat && \
    rm -rf apache-tomcat-${VERSION}.tar.gz /usr/local/tomcat/webapps/* && \
    mkdir /usr/local/tomcat/webapps/ROOT
ADD ./index.html /usr/local/tomcat/webapps/ROOT/
ADD ./jdk-8u91-linux-x64.tar.gz /
RUN mv /jdk1.8.0_91/ /usr/local/jdk
EXPOSE 8080
CMD ["/usr/local/tomcat/bin/catalina.sh","run"]

3、构建镜像

docker build -t tomcat:v1 .

4、创建并启动容器

docker run -d -p 8080:8080 tomcat:v1

docker ps -a

curl 192.168.10.11:8080

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • iptables使用及docker的iptables规则

    iptables使用及docker的iptables规则

    Docker在创建容器时,会自动添加一些iptables规则来实现网络隔离和转发等功能,本文主要介绍了iptables使用及docker的iptables规则,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • docker images的常用方式

    docker images的常用方式

    这篇文章主要介绍了docker images的常用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • 详解Docker 下开发 hyperf 完整使用示例

    详解Docker 下开发 hyperf 完整使用示例

    这篇文章主要介绍了详解Docker 下开发 hyperf 完整使用示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • docker安装minio无法访问的解决

    docker安装minio无法访问的解决

    这篇文章主要介绍了docker安装minio无法访问的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Mac上使用Docker如何快速启动MySQL测试

    Mac上使用Docker如何快速启动MySQL测试

    本文主要讨论如何使用Docker快速启动 MySQL 测试,包括Mac环境。非常不错,具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-10-10
  • docker和docker-compose的版本对应关系的实现

    docker和docker-compose的版本对应关系的实现

    本文主要介绍了docker和docker-compose的版本对应关系的实现,两者虽非强制绑定,但新版本docker-compose可能依赖更高版本Docker引擎的API,具有一定的参考价值,感兴趣的可以了解一下
    2025-06-06
  • 虚拟机如何安装指定版本的Docker举例详解

    虚拟机如何安装指定版本的Docker举例详解

    这篇文章主要介绍了虚拟机如何安装指定版本的Docker的相关资料,包括配置yum源、查看可用版本、安装指定版本、卸载旧版本、解决冲突、再次安装以及最后验证安装,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-12-12
  • Docker为网络bridge模式指定容器ip的方法

    Docker为网络bridge模式指定容器ip的方法

    Docker在创建容器时有四种网络模式,bridge为默认不需要用--net去指定,其他三种模式需要在创建容器时使用--net去指定。那Docker为网络bridge模式指定容器ip该如何实现呢?下面通过通过这篇文章一起看看吧,文中给出了详细的示例代码,有需要的可以参考借鉴。
    2016-11-11
  • Docker容器日志查看和清理的图文教程

    Docker容器日志查看和清理的图文教程

    docker容器在运行过程中会产生日志,日志的量跟具体的容器有关,下面这篇文章主要给大家介绍了关于Docker容器日志查看和清理的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • SQL Server 简介与 Docker Compose 部署SQL Server 容器

    SQL Server 简介与 Docker Compose 部署SQL Server 容器

    SQL Server 是一个功能强大的关系型数据库管理系统,适用于各种规模的应用程序和数据存储需求,在本文中,我将简要介绍 SQL Server 的基本概念,并详细阐述如何使用 Docker Compose 部署 SQL Server 容器,感兴趣的朋友跟随小编一起看看吧
    2023-10-10

最新评论