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 
posted @ 2021-03-23 21:09  云崖君  阅读(134)  评论(0编辑  收藏  举报