使用Dockerfile创建镜像过程
作者:LKAI.
实验环境
安装好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
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。