Docker 镜像制作
基础工作
commit命令
如果你有一个容器正在运行中,同时你对其增加了许多扩展性的功能,如在centos镜像容器中安装了LAMP服务,若想对其持久化保存,以方便后面一键部署该服务,则可以将该镜像容器制作为一个自定义镜像,通过commit命令完成制作:
$ docker commit 容器名 自定义名/自定义TAG
后面部署时,你只需要拿着该镜像生成容器即可一键完成部署。
在下面的学习中,我们将开始利用基础镜像centos6来构建一个LAMP容器,并将该容器生成为一个自定义镜像。
本地yum
在docker宿主机中,制作一个yum本地源,用于容器中各种服务的安装:
$ yum install -y vsftpd
$ systemctl enable vsftpd
$ systemctl start vsftpd
将docker宿主机中的centos6镜像上传并进行挂载:
$ mkdir -p /var/ftp/centos6.9
$ mount -o loop /mnt/CentOS-6.9-x86_64-bin-DVD1.iso /var/ftp/centos6.9/
在外部机上进行ftp服务验证,打开浏览器输入以下地址:
ftp://192.168.0.120/centos6.9/
给docker宿主机的Linux制作本地yum源:
$ cat >/etc/yum.repos.d/ftp_6.repo <<EOF
[ftp]
name=ftpbase
baseurl=ftp://192.168.0.120/centos6.9
enabled=1
gpgcheck=0
EOF
镜像构建
基础镜像
创建存放mysql等数据的数据目录,进行映射:
$ mkdir -p /opt/vol/mysql /opt/vol/html
下载centos6的官方基础镜像:
$ docker pull centos:6.9
创建该镜像的基础容器并启动:
$ docker run -it --name="centos" -v /opt/vol/mysql:/var/lib/mysql -v /opt/vol/html:/var/www/html centos:6.9
删除自带的yum源:
$ mv /etc/yum.repos.d/*.repo /tmp
添加本地docker宿主机上的ftp服务yum源:
$ echo -e "[ftp]\nname=ftp\nbaseurl=ftp://172.17.0.1/centos6.9\ngpgcheck=0">/etc/yum.repos.d/ftp.repo
# 因为docker容器启动后都会从172.17.0.2向后分配IP地址
# 而docker宿主机为172.17.0.1,则如此配置即可
创建yum缓存:
$ yum makecache fast
安装所需要的所有软件包:
$ yum makecache fast && yum install openssh-server htppd mysql mysql-server php php-mysql -y
ssh初始化
由于我们是centos6的系统,不用systemctl进行管理,直接使用init.d的脚本形式管理sshd即可:
$ /etc/init.d/sshd start
$ /etc/init.d/sshd stop
# ssh第一次启动时,需要生成秘钥,生成pam验证配置文件
# 所以这里启动一次
提供sshd服务的机器root用户必须有密码,所以给root用户设置一个密码:
$ passwd root 123456
mysql初始化
mysql安装完成之后,对其进行初始化功能:
$ /etc/init.d/mysqld start
mysql> grant all on *.* to root@'%' identified by '123';
mysql> grant all on *.* to discuz@'%' identified by '123';
mysql> create database discuz charset utf8;
apache初始化
执行以下命令:
$ /etc/init.d/httpd start
第一版镜像
现在我们所有基础的服务都装完了,需要生成自定义镜像并进行测试功能服务是否都正常:
$ docker commit centos test/centos_lamp:v1
然后根据这个新镜像启动新容器,进行服务测试:
$ docker run -it --name="centos_v1" -v /opt/vol/mysql:/var/lib/mysql -v /opt/vol/html:/var/www/html -p 8080:80 test/centos_lamp:v1
启动mysqld与apache:
$ /etc/init.d/mysqld start
$ /etc/init.d/httpd start
下载dz论坛并上传到/opt/vol/html目录中进行解压。
第二版镜像与启动脚本
dz论坛已经上传完毕了,并且所有服务的功能都正常,我们来制作第二版镜像:
$ docker commit centos_v1 test/centos6.9_sshd_lamp_dz:v2
由于镜像启动后,还要启动很多服务功能,所以我们可以在数据映射目录中添加一个启动脚本:
$ cd /opt/vol/html
$ vim init.sh
#!/bin/bash
/etc/init.d/mysqld start
/etc/init.d/httpd start
/usr/sbin/sshd -D
$ chmod 777 init.sh
# mysqld和httpd都只是启动一次即可开启服务
# 而sshd需要持久化服务,所以需要加-D的参数
结果测试
接下来我们的第二版镜像与启动脚本都制作完成了。
基于该镜像尝试启动一个容器:
$ docker container run -d --name="centos_sshd_lamp_bbs" -v /opt/vol/mysql:/var/lib/mysql -v /opt/vol/html:/var/www/html -p 22222:22 -p 8888:80 -p 33060:3306 test/centos6.9_sshd_lamp_dz:v2 /var/www/html/init.sh
# 启动时,指定其运行/var/www/html/init.sh脚本启动各种服务
# 由于是数据目录映射,所以即使镜像中没有这个脚本,但通过映射也能找到
centos7的sshd
centos7中的ssh服务不能通过init.d的脚本形式管理,这与开机流程有很大关系。
centos7中为了加速开机启动,采用systemctl进行启动管理,所以sshd的启动与centos6有很大的区别。
如果你想单独构建一个centos7+sshd服务的镜像,可以像下面这样做:
$ mv /etc/yum.repos.d/*.repo /tmp
$ echo -e "[ftp]\nname=ftp\nbaseurl=ftp://172.17.0.1/centos7.5\ngpgcheck=0">/etc/yum.repos.d/ftp.repo
$ yum makecache fast && yum install openssh-server -y
$ mkdir /var/run/sshd
$ echo 'UseDNS no' >> /etc/ssh/sshd_config
$ sed -i -e '/pam_loginuid.so/d' /etc/pam.d/sshd
$ echo 'root:123456' | chpasswd
$ /usr/bin/ssh-keygen -A
$ docker commit centos7_sshd centos7
$ docker container run -d --name="c7shhd" -p 222:22 centos7_sshd /usr/sbin/sshd -D
# 容器name是centos7,镜像名字是centos7_sshd
# /usr/sbin/sshd -D指的是将启动sshd服务的脚本优先执行,-D代表永不结束
Dockerfile
如何使用
手工进行镜像构建太麻烦,只要步骤正确我们可以将这些步骤做成脚本。
第一步你应该创建一个dockerfile文件夹,并且创建一个准备构建镜像完成后名字的文件夹。
$ mkdir -p /opt/dockerfile/centos6.9_sshd
在这个构建镜像名字的文件夹中,创建一个dockerfile文件:
$ vim Dockerfile
# 首字母大写
基础语法
第一行是基于的镜像:
FROM centos:6.9
第二行开始就可以书写命令了,如普通的shell命令用RUN进行指定:
RUN mv /etc/yum.repos.d/*.repo /tmp && echo -e "[ftp]\nname=ftp\nbaseurl=ftp://172.17.0.1/centos6.9\ngpgcheck
=0">/etc/yum.repos.d/ftp.repo && yum makecache fast && yum install openssh-server htppd mysql mysql-server php php-mysql -y
# 如果RUN命令要执行一些特殊的shell命令,如 mysql -uroot -p123
# 则可以通过下面这种方式书写:
# RUN ["mysql", "-uroot", "-p123"]
注意,多个shell命令最好通过&&进行链接写到一行,因为在dockerfile脚本执行中,每执行一行run都会生成一个临时容器,为了减少生成的临时容器数量,shell命令写到一行很好
第三行,依旧是RUN,启动一些最基础的服务:
RUN /etc/init.d/sshd start && echo "123456" | passwd root --stdin && /etc/init.d/mysqld start && /etc/init.d/httpd start
第四行介绍一个新命令,COPY,它可以将 /dockerfile/镜像名字/某个文件 上传至容器指定目录中,支持通配符*:
COPY init.sh /
# 将/opt/dockerfile/centos6.9_sshd/init.sh上传到容器的根目录下
# init.sh是为了初始化数据库,所以用一个脚本写下命令
-----------------------
#!/bin/bash
/etc/init.d/mysqld start
mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database d
iscuz charset utf8;"
/etc/init.d/httpd start
/usr/sbin/sshd -D
-----------------------
第五行也有一个新命令,ADD,和COPY类似,必须将文件放在 /dockerfile/镜像名字/ 这个目录下,但是如果文件名称中含有tar,则会自动解压并上传至容器,还支持url的互联网资源文件,但是对于url互联网资源文件的后缀含有tar的不会进行解压:
ADD bbs.tar.gz /var/www/html/
# 上传dz代码,自动解压到/var/www/html/目录下
第六行至第八行,都是告诉镜像使用者,会开启哪些端口,但是并不会做映射:
EXPOSE 22
EXPOSE 80
EXPOSE 3306
最后一行是CMD,代表容器启动执行的脚本:
CMD ["/bin/bash","/init.sh"]
# 这代表会使用/bin/bash执行根目录下的/init.sh脚本
完整的一个dockerfile如下:
FROM centos:6.9
RUN mv /etc/yum.repos.d/*.repo /tmp && echo -e "
[ftp]\nname=ftp\nbaseurl=ftp://172.17.0.1/centos6.9\ngpgcheck=0">/etc/yum.repos.d/ftp
.repo && yum makecache fast && yum install openssh-server htppd mysql mysql-server php php-mysql -y
RUN /etc/init.d/sshd start && echo "123456" | passwd root --stdin && /etc/init.d/mysqld start && /etc/init.d/httpd start
COPY init.sh /
ADD bbs.tar.gz /var/www/html/
EXPOSE 22
EXPOSE 80
EXPOSE 3306
CMD ["/bin/bash","/init.sh"]
然后是init.sh:
#!/bin/bash
/etc/init.d/mysqld start
mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database d
iscuz charset utf8;"
/etc/init.d/httpd start
/usr/sbin/sshd -D
常用指令
FORM指令,规定从哪个基础镜像中开始构建自定义镜像:
FORM centos:6.9
RUN指令,在容器中运行的shell命令,推荐一行多个shell命令,用&&链接:
# 普通命令
RUN mv /etc/yum.repos.d/*.repo
# 带参命令
RUN [“mysql”, “-uroot”, “-p123”]
COPY指令,将dockerfile/imageName/下的文件上传至容器某个目录中:
COPY init.sh /
# 将/opt/dockerfile/centos6.9_sshd/init.sh上传到容器的根目录下
ADD指令,将dockerfile/imageName/下的文件上传至容器某个目录中,如果含有tar后缀,则自动解压,如果是url资源,即使是含有tar后缀也不会自动解压:
# 会自动解压,将/opt/dockerfile/centos6.9_sshd/bbs.tar.gz上传到容器的/var/www/html目录下并自动解压
ADD bbs.tar.gz /var/www/html/
# 不会自动解压
ADD https://mirrors.aliyun.com/centos/7.6.1810/os/x86_64/Packages/centos-bookmarks-7-1.el7.noarch.rpm /tmp
EXPOSE指令,声明容器中会使用的端口,仅声明,不做映射,主要给使用者看,方便用-p做端口映射:
EXPOSE 22
EXPOSE 80
EXPOSE 3306
VOLUME指令,容器的映射目录数据卷,在启动时可以不用加-v参数指定写入的目录,该配置生效:
VOLUME ["/var/www/html", "/data/mysql/data"]
WORKDIR指令,类似于CD命令,切换容器内shell的工作目录:
WORKDIR /
ENV指令,在dockerfile中指定变量后引用:
ENV CODEDIR /var/www/html/
ENV DATADIR /data/mysql/data
ADD bbs.tar.gz ${CODEDIR}
VOLUME ["${CODEDIR}","${DATADIR}"]
CMD指令,指定启动容器时,容器第一个运行的进程脚本,但是可以被手动替换:
CMD ["/bin/bash","/init.sh"]
# 这代表会使用/bin/bash执行根目录下的/init.sh脚本
# 这个就替换了init.sh脚本的执行
# docker run -it --name="centos00112" centos:7.5.1804 /usr/sbin/sshd -D
ENTRYPOINT指令,指定启动容器时,容器第一个运行的进程脚本,不可以被手动替换,防止容器秒启秒停:
ENTRYPOINT ["/bin/bash","/init.sh"]
如何使用
在dockerfile/imagName/所在目录中执行:
$ docker build -t centos:6.9
制作完成后启动容器(先查看生成的image信息):
$ docker container run -d --name="centos_sshd_lamp_bbs_2" -p 22222:22 -p 8888:80 -p 33060:3306 d2bcdbdfd0f8