目录
一、在编写 Dockerfile 时,有严格的格式需要遵循
二、Dockerfile 操作常用的指令
2.1ENTRYPOINT和CMD共存的情形
2.2ENTRYPOINT和CMD的区别
2.3ADD 与COPY的区别
三、Dockerfile案例
3.1构建apache镜像
3.1.1 创建镜像目录方便管理
3.1.2创建编写dockerfile文件
3.1.3生成镜像
3.1.4启动容器
3.2构建sshd镜像
3.2.1创建镜像目录方便管理
3.2.2 创建编写dockerfile文件
3.2.3生成镜像
编辑3.2.4启动容器并修改root密码
3.3构建Systemctl镜像
3.3.1创建镜像目录方便管理
3.3.2 创建编写dockerfile文件
3.3.3生成镜像
3.3.4启动容器,并挂载宿主机目录挂载到容器中,和进行初始化
3.3.5进入容器
3.4构建nginx镜像
3.4.1创建镜像目录方便管理
3.4.2创建编写dockerfile文件
3.4.3创建新镜像
3.4.4启动容器
3.4.5浏览器访问检测
3.5构建tomcat 镜像
3.5.1创建镜像目录方便管理
3.5.2创建编写dockerfile文件
3.5.3创建新镜像
3.5.4启动容器
3.5.5浏览器访问
3.6构建mysql镜像
3.6.1创建镜像目录方便管理
3.6.2创建编写dockerfile文件
3.6.3创建新镜像
3.6.4启动容器,并进行初始化
3.6.5进容器给权限
3.6.6进入容器,授权远程连接 mysql
3.6.7在客户端连接mysql容器
四、镜像容量过大的解决方案
创建镜像有三种方法,分别为基于已有镜像创建、基于本地模板创建以及基于Dockerfile创建
一、在编写 Dockerfile 时,有严格的格式需要遵循
- 第一行必须使用 FROM 指令指明所基于的镜像名称;
- 之后使用 MAINTAINER 指令说明维护该镜像的用户信息;
- 然后是镜像操作相关指令,如 RUN 指令。每运行一条指令,都会给基础镜像添加新的一层
- 最后使用 CMD 指令指定启动容器时要运行的命令操作。
二、Dockerfile 操作常用的指令
详细解读参见上一篇文章
2.1ENTRYPOINT和CMD共存的情形
ENTRYPOINT和CMD共存的情形:ENTRYPOIN 指定命令,CMD 传参
容器运行时的优先级:
docker run --entrypoint ---> Dockerfile ENTRYPOINT ----> docker run命令---> Dockerfile CMD
2.2ENTRYPOINT和CMD的区别
ENTRYPOINT 设定容器启动时第一个运行的命令;CMD 是启动容器时默认执行的命令,如果指定多条CMD命令,只执行最后一 条命令。
如果在 docker run 时指定了命令或者镜像中有 ENTRYPOINT,那么 CMD 就会被覆盖,并且会将 CMD 中的命令作为参数传给 ENTRYPOINT。
CMD 可以为 ENTRYPOINT 进行传参。
2.3ADD 与COPY的区别
add 和copy的区别
都具有复制文件或者目录到镜像的功能
- copy 只能复制本地的文件或者目录
- add 源文件可以使用 URL路径,在线下载文件复制到镜像当中。且复制tar 压缩的压缩包时候,可以自动解压
三、Dockerfile案例
3.1构建apache镜像
mkdir /opt/apache
cd /opt/apache
#创建并进入文件夹,每个服务一个文件夹
vim Dockerfile
#创建Dockerfile文件,文件内容如下
FROM centos:7
#基于的基础镜像指定为centos:7,注意本机要有此基础镜像
MAINTAINER this is apache image <test>
#说明镜像维护人信息为,指定用户为test
RUN yum -y update
RUN yum -y install httpd
#镜像RUN指令指定启动容器后的运行命令,yum安装update和httpd服务
EXPOSE 80
#开启80端口
ADD index.html /var/www/html/index.html
#复制宿主机index.html文件到容器的 /var/www/html/index.html
ENTRYPOINT ["/usr/sbin/apachectl"]
CMD ["-D","FOREGROUND"]
#使用前台启动apache注意使用绝对路径,如果后台启动,启动完shell就结束了容器就结束了,保存退出。
echo "this is test web">index.thml
#准备网站的网页,注意必须在和Dockerfile文件相同的目录
docker build -t httpd:centos .
#将dockerfile 文件生成镜像注意最后有个点。
docker run -d -p 40330:80 httpd:centos
#新镜像运行容器,映射宿主机的40330端口为容器的80端口
访问192.168.30.11:40330 进行测试是否可以访问容器的httpd主业
apache即httpd服务
3.1.1 创建镜像目录方便管理
3.1.2创建编写dockerfile文件
FROM centos:7
MAINTAINER this is apache image <nanjing>
RUN yum -y update
RUN yum -y install httpd
EXPOSE 80
ADD index.html /var/www/html/index.html
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
3.1.3生成镜像
3.1.4启动容器
浏览器访问
3.2构建sshd镜像
mkdir /opt/sshd
cd /opt/sshdvim Dockerfile
FROM centos:7
#指定sshd基于centos:7的镜像
MAINTAINER this is ssh image <ssh>
#说明镜像信息,镜像用户为ssh
RUN yum -y update
#此内容若保存可注释掉
#运行RUN指令执行update更新
RUN yum -y install openssh* net-tools lsof telnet passwd
#RUN指令执行安装openssh相关工具,net工具,lsof、telnet、passwd程序
RUN echo "abc123" |passwd --stdin root
#免交互设置root密码为abc123
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
#关闭sshd服务的pam认证
RUN sed -ri '/^session\s+required\s+pam_loginuid.so/ s/^/#/' /etc/pam.d/sshd
#取消pam限制 \s+表示制表符,例如他有固定空格空几格等等
RUN ssh-keygen -t rsa -A
#生成秘钥认证文件
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
#递归创建/root/.ssh文件夹并修改属主属租为root,添加权限为700只允许属组属组用户操作
EXPOSE 22
#规定端口为22
ENTRYPOINT [ "/usr/sbin/sshd" ]
CMD ["-D", "FOREGROUND"]
#/usr/sbin/sshd -D用于前台启动sshd服务docker build -t sshd:centos .
#创建sshd;centos镜像docker run -d -p 40022:22 sshd:centos
#运行sshd:centos容器并映射容器中的22端口为40022端口
docker ps
#查看容器信息
ssh localhost -p 40022
ifconfig
#宿主机执行验证sshd容器
3.2.1创建镜像目录方便管理
3.2.2 创建编写dockerfile文件
FROM centos:7
MAINTAINER this is ssh image <wutong>
RUN yum -y install openssh* net-tools lsof telnet passwd
RUN echo 'abc1234' | passwd --stdin root
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
RUN sed -ri '/^session\s+required\s+pam_loginuid.so/ s/^/#/' /etc/pam.d/sshd
RUN ssh-keygen -t rsa -A
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
EXPOSE 22
CMD ["/usr/sbin/sshd" , "-D"]
3.2.3生成镜像
docker build -t sshd:centos .
3.2.4启动容器并修改root密码
docker run -d --name sshd -P sshd:centos
docker ps
ssh localhost -p 32768
3.3构建Systemctl镜像
mkdir /opt/systemctl
cd /opt/systemctlvim DockerfileFROM sshd:centos
MAINTAINER this is systemctl image <hmj>
ENV container docker
#除了systemd-tmpfiles-setup.service,删除其它所有文件
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*; \
rm -f /etc/systemd/system/*.wants/*; \
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
#CMD ["/usr/sbin/init"]//生成镜像
docker build -t systemd:centos .//启动容器,并挂载宿主机目录挂载到容器中,和进行初始化
docker run --privileged -d -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init
#--privileged:使container内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。docker ps -a//进入容器
docker exec -it a0d624d2bfa9 bashsystemctl status sshd方法二:
docker run --privileged -it -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init &
3.3.1创建镜像目录方便管理
3.3.2 创建编写dockerfile文件
FROM sshd:centos
MAINTAINER this is systemctl image <xiaoliu>
ENV container docker
#除了systemd-tmpfiles-setup.service,删除其它所有文件
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*; \
rm -f /etc/systemd/system/*.wants/*; \
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
#CMD ["/usr/sbin/init"]
3.3.3生成镜像
docker build -t systemd:centos .
3.3.4启动容器,并挂载宿主机目录挂载到容器中,和进行初始化
docker run --privileged -d -P -v /sys/fs/cgroup/:/sys/fs/cgroup:ro systemd:centos /sbin/init
3.3.5进入容器
docker exec -it 17b629646884 bashsystemctl start sshd
systemctl status sshd
如果你想开启,容器还是可以再次开启的哦
方法二
docker run --privileged -it -P -v /sys/fs/cgroup:/sys/fs/cgroup:ro systemd:centos /sbin/init &
3.4构建nginx镜像
mkdir /opt/nginx
cd /opt/nginx/
cp /opt/nginx-1.18.0.tar.gz /opt/nginx
------------------------------------------------vim Dockerfile#基于基础镜像
FROM centos:7
#用户信息
MAINTAINER this is nginx image <hmj>
#添加环境包
RUN yum -y update
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make
RUN useradd -M -s /sbin/nologin nginx
#上传nginx软件压缩包,并解压
ADD nginx-1.18.0.tar.gz /opt/
#指定工作目录
WORKDIR /opt/nginx-1.18.0
RUN ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module && make && make install
ENV PATH /usr/local/nginx/sbin:$PATH
#指定http和https端口
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf #关闭 nginx 在后台运行
#添加宿主机中run.sh到容器中
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
#CMD ["/usr/local/sbin/nginx", "-g", "daemon off;"]----------------------------------------
vim run.sh
#!/bin/bash
/usr/local/nginx/sbin/nginx//创建新镜像
docker build -t nginx:centos .docker run -d -P nginx:centosdocker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2bd72ca9824d nginx:centos "/run.sh" 29 minutes ago Up 4 seconds 0.0.0.0:32771->80/tcp, :::32771->80/tcp, 0.0.0.0:32770->443/tcp, :::32770->443/tcp nginxhttp://192.168.80.10:32771
3.4.1创建镜像目录方便管理
3.4.2创建编写dockerfile文件
FROM centos:7
MAINTAINER MAINTAINER this is nginx image <xiaoyu>
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make
RUN useradd -M -s /sbin/nologin nginx
ADD nginx-1.18.0.tar.gz /opt/
WORKDIR /opt/nginx-1.18.0
RUN ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module && make && make install
ENV PATH /usr/local/nginx/sbin:$PATH
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf
ADD run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]
vim run.sh
#!/bin/bash
/usr/local/nginx/sbin/nginx
3.4.3创建新镜像
ocker build -t nginx:centos .
3.4.4启动容器
docker run -d --name nginx -P nginx:centos
3.4.5浏览器访问检测
3.5构建tomcat 镜像
mkdir /opt/tomcat
cd /opt/tomcat
cp /opt/jdk-8u91-linux-x64.tar.gz /opt/tomcat
cp /opt/apache-tomcat-8.5.16.tar.gz /opt/tomcatvim DockerfileFROM centos:7
MAINTAINER this is tomcat image <hmj>
ADD jdk-8u91-linux-x64.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv jdk1.8.0_91 /usr/local/java
ENV JAVA_HOME /usr/local/java
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $JAVA_HOME/bin:$PATH
ADD apache-tomcat-8.5.16.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv apache-tomcat-8.5.16 /usr/local/tomcat
EXPOSE 8080
#CMD ["/usr/local/tomcat/bin/catalina.sh","run"]
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
CMD ["/usr/local/tomcat/bin/startup.sh","start"]//创建新镜像
docker build -t tomcat:centos .docker run -d --name tomcat01 -p 1216:8080 tomcat:centos http://192.168.80.10:1216
3.5.1创建镜像目录方便管理
注意自己的安装包哦,版本哦
3.5.2创建编写dockerfile文件
FROM centos:7
MAINTAINER this is tomcat image <xiaozi>
ADD jdk-8u291-linux-x64.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv jdk1.8.0_291 /usr/local/java
ENV JAVA_HOME /usr/local/java
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $JAVA_HOME/bin:$PATH
ADD apache-tomcat-9.0.16.tar.gz /usr/local/
WORKDIR /usr/local/
RUN mv apache-tomcat-9.0.16 /usr/local/tomcat
EXPOSE 8080
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
CMD ["/usr/local/tomcat/bin/startup.sh","start"]
3.5.3创建新镜像
docker build -t tomcat:centos .
3.5.4启动容器
docker run -d --name tomcat -p 1216:8080 tomcat:centos
3.5.5浏览器访问
3.6构建mysql镜像
mkdir /opt/mysqld
cd /opt/mysqldvim DockerfileFROM centos:7
MAINTAINER this is mysql image <hmj>
RUN yum -y install ncurses ncurses-devel bison cmake pcre-devel zlib-devel gcc gcc-c++ make;useradd -M -s /sbin/nologin mysql
ADD mysql-boost-5.7.20.tar.gz /usr/local/src/
WORKDIR /usr/local/src/mysql-5.7.20/
RUN cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DSYSCONFDIR=/etc \
-DSYSTEMD_PID_DIR=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DWITH_BOOST=boost \
-DWITH_SYSTEMD=1;make -j4;make install
ADD my.cnf /etc/my.cnf
EXPOSE 3306
RUN chown -R mysql:mysql /usr/local/mysql/;chown mysql:mysql /etc/my.cnf
WORKDIR /usr/local/mysql/bin/
RUN ./mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data;cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/;systemctl enable mysqld
ENV PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH
VOLUME [ "/usr/local/mysql" ]
CMD ["/usr/sbin/init"]vim my.cnf
[client]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock[mysql]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTESvim run.sh
#!/bin/bash
/usr/local/mysql/bin/mysqld
systemctl enable mysqld//创建新镜像
docker build -t mysql:centos .//启动容器,并进行初始化
docker run --name=mysql_server -d -P --privileged mysql:centos /usr/sbin/init//进容器给权限
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f9a4d8f6c65f mysql:centos "/usr/sbin/init" 17 seconds ago Up 16 seconds 0.0.0.0:49153->3306/tcp mysql_server//进入容器,授权远程连接 mysql
docker exec -it f9a4d8f6c65f /bin/bashmysql -u root -p
grant all privileges on *.* to 'root'@'%' identified by 'abc123';
grant all privileges on *.* to 'root'@'localhost' identified by 'abc123';
flush privileges;//在客户端连接mysql容器
mysql -h 192.168.80.10 -u root -P 49153 -pabc123
3.6.1创建镜像目录方便管理
3.6.2创建编写dockerfile文件
FROM centos:7
MAINTAINER this is mysql image <hmj>
RUN yum -y install ncurses ncurses-devel bison cmake pcre-devel zlib-devel gcc gcc-c++ make;useradd -M -s /sbin/nologin mysql
ADD mysql-boost-5.7.20.tar.gz /usr/local/src/
WORKDIR /usr/local/src/mysql-5.7.20/
RUN cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DSYSCONFDIR=/etc \
-DSYSTEMD_PID_DIR=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DWITH_BOOST=boost \
-DWITH_SYSTEMD=1;make -j4;make install
ADD my.cnf /etc/my.cnf
EXPOSE 3306
RUN chown -R mysql:mysql /usr/local/mysql/;chown mysql:mysql /etc/my.cnf
WORKDIR /usr/local/mysql/bin/
RUN ./mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data;cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/;systemctl enable mysqld
ENV PATH=/usr/local/mysql/bin:/usr/local/mysql/lib:$PATH
VOLUME [ "/usr/local/mysql" ]
CMD ["/usr/sbin/init"]
[client]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock[mysql]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock[mysqld]
user = mysql
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
port = 3306
character_set_server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES
#!/bin/bash
/usr/local/mysql/bin/mysqld
systemctl enable mysqld
3.6.3创建新镜像
docker build -t mysql:centos .
3.6.4启动容器,并进行初始化
docker run --name=mysql_server -d -P --privileged mysql:centos /usr/sbin/init
这里报错了,重新修在再docker built 如下图
3.6.5进容器给权限,进入容器,授权远程连接 mysql
docker exec -it 38108c6216e4 /bin/bash
grant all privileges on *.* to 'root'@'%' identified by '123123';
grant all privileges on *.* to 'root'@'localhost' identified by '123123';
flush privileges;
3.6.7在客户端连接mysql容器
mysql -h 192.168.246.8 -uroot -P 32773 -p123123
再重新开启一台装有mysql的机器做客户端进行连接
四、镜像容量过大的解决方案
- 基础镜像尽量使用轻量级最小化的镜像。
- Dockerfile 中尽量把 RUN 指令合并在一起,减少镜像的层数(因为每一个RUN指令就是一个镜像层)。
- 多级构建(拿 Dockerfile 构建好的镜像再构建一次)
Dockerfile 总结:基于dockerfile 镜像
1、dockerfile 构建镜像的步骤
先用FROM 指令指定基础镜像
再用MAINTINER 指定维护人信息
然后再用 RUN EXPOSE ADD ENV USER WORKDIR指令编写镜像的过程
最后使用 CMD 或者 ENTPYONT 指令指定启动容器时执行的命令
2、ENTPYONT CMD 区别
容器启动时执行命令的优先级
docker run --entypont=命令 镜像 选项 参数 ---> ENTPYONT ["命令","选顶","参数”] ---> docker run 镜像 命令 选项 参数 ---> CMD ["命令","选项","参数"]
如果在同一个 dockerfile 文件中同时存在 ENTPYONT 和 CMD 时,ENTPYONT 会覆盖 CMD 运行命令,CMD 为提供选项和参数
3、ADD 和 COPY 区别
都可以复制本地文件/目录到镜像中
ADD 可以通过URL路径下 文件并复制到镜像 还可以把本地的tar压缩包进行解压后复制到镜像COPY 支持配合 --from= 选项 实现多个阶段构建
4、如何缩小 dockerfile 构建的镜像体积大小?
仅可能减少指令的数量,比如把 RUN 的 linux 命令进行合并
仅可能的使用最简洁的基础镜像
使用多阶段(多级)构建