小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
8. 通过 dockerfile 定制企业镜像
8.1 dockerfile 的基本使用初体验(centos6.9_sshd)
- 创建存放 dockerfile 的目录
mkdir -p /opt/dockerfile
- 创建目录
cd /opt/dockerfile/
mkdir centos6.9_ssh
- 编写 Dockerfile。
cd /opt/dockerfile/centos6.9_ssh
vim Dockerfile
# Centos6.9-SSHDv1.0
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 -y
RUN /etc/init.d/sshd start && /etc/init.d/sshd stop && echo "123456" | passwd root --stdin
EXPOSE 22
EXPOSE 80
CMD ["/usr/sbin/sshd","-D"]
- Dockerfile 指令介绍、语法介绍
-
FROM:基础镜像 -
第一个非注释行必须是
FROM -
FROM语法:
-
centos:6.9
-
centos@2199b8eb8390(更安全)
-
RUN指令:构建镜像过程中运行的命令 -
RUN语法:
-
基于 bash 类的命令。
-
和 shell 中的语法格式是一样的。可以使用
&&接多个命令。 -
而且在 Dockerfile 中我们建议在做 shell 命令时 尽量能写到一个行上就写到一个行上。
-
上面的要求是基于 dockerfile 构建镜像的流程:
-
模仿了手工制作的流程,但是更加繁琐一些;
-
dockerfile 中的每一行去执行时都会生成一个临时性的容器(中间容器)
-
基于 bash 类的命令仅限于 bash 支持的命令,在最前面会默认加
/bin/bash或/bin/sh -c -
会先运行一个 shell 进程,然后再去执行这些命令
-
其他命令(非 bash)
-
比如 mysql 命令:
mysqld --initialize-insecure --user=mysql --bashdir=/usr/local/mysql --datadir=/data/mysql/data -
使用
[]将命令阔起来 -
示例:
["mysqld","--initialize-insecure","--user=mysql","--bashdir=/usr/local/mysql","--datadir=/data/mysql/data"] -
第一个位置是 命令本身
-
其他位置是 选项或者参数
-
使用逗号、引号区分
-
一般情况下,我们会将这种命令写在脚本中,调用脚本来实现。
-
RUN可以写多个 -
EXPOSE指令:向外暴露端口 -
语法:
-
EXPOSE PORT -
可以暴露多个端口
-
CMD指令:使用镜像启动容器时运行的命令 -
CMD语法: -
同
RUN中非 bash 语法,例如:CMD ["/usr/sbin/sshd","-D"] -
标识 dockerfile 的结束。
-
在使用镜像启动容器之后,执行的命令
- 使用 Dockerfile 构建镜像(会自动找到 Dockerfile 文件)
docker image build -t "wys_centos6.9-sshd:v1.0" ./
Step 2/6 : 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 -y
---> Running in 7cb22a8774c7
7cb22a8774c7 表示临时容器,临时容器可以登录。记得要使用 --rm,不要产生多余的临时容器,临时容器退出应该删掉。
centos6.9_ssh]# docker container run -it --rm c16c8f81cebf /bin/bash
- 查看镜像(none 表示临时镜像)
[root@VM-0-3-centos centos6.9_ssh]# docker image ls -a
REPOSITORY TAG IMAGE ID CREATED SIZE
wys_centos6.9-sshd v1.0 c16c8f81cebf 6 minutes ago 331 MB
<none> <none> f1a973938e62 6 minutes ago 331 MB
<none> <none> 6a8a8f3b17aa 6 minutes ago 331 MB
<none> <none> 73f93aa20247 6 minutes ago 331 MB
<none> <none> b917446275b6
- 使用镜像启动容器
docker container run -d wys_centos6.9-sshd:v1.0
- 查看镜像
[root@VM-0-3-centos centos6.9_ssh]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb5b2b0e50e1 wys_centos6.9-sshd:v1.0 "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 22/tcp, 80/tcp practical_kare
- 查看容器地址
docker container inspect cb5b2b0e50e1
"IPAddress": "172.17.0.3"
- 测试连接,发现可以正常登录
ssh 172.17.0.3
8.2 制作 LAMP + BBS 镜像,介绍 COPY 和 ADD 命令
- 准备 discuz tar 类型压缩包。我们下载的是 .zip 格式的压缩包。
unzip -o -d /tmp/discuz /root/Discuz_X3.2_SC_UTF8.zip
cd /tmp/discuz/
tar zcvf discuz.tar.gz ./*
mv discuz.tar.gz /root/
- 创建 lamp 目录
mkdir -p /opt/dockerfile/lamp
cd /opt/dockerfile/lamp/
- 编写 Dockerfile
# Centos6.9_sshd_LAMP
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
RUN mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database discuz charset utf8;"
COPY init.sh /
ADD discuz.tar.gz /var/www/html/
ADD https://mirrors.aliyun.com/centos-vault/6.9/os/x86_64/Packages/edac-utils-devel-0.9-16.el6.x86_64.rpm /tmp/
EXPOSE 22
EXPOSE 80
EXPOSE 3306
CMD ["/bin/bash", "/init.sh"]
-
COPY指令:将宿主机文件复制到容器中 -
COPY语法: -
... :源可以有多个
-
COPY 宿主机文件 容器地址 -
支持通配符
-
必须和 Dockerfile 同一级别。比如我们将初始化脚本和 discuz 压缩包复制过来,后面会用到:
cp /opt/vol/html/init.sh ./,cp /root/discuz.tar.gz ./ -
如果拷贝的是目录,只拷贝目录下的子文件和目录
-
ADD指令:复制(同 COPY,也是将文件拷贝到容器内部) + 自动解压 .tar* 压缩文件 -
ADD语法: -
... :源可以有多个
-
-
ADD 宿主机文件 容器地址 -
ADD URL文件 容器地址 -
对于压缩文件会自动解压(.tar 类型):
.tar.gz,.tar.bz2,.tar.xz,.tar -
如果容器地址目录不存在,会自动创建
-
ADD 还可以传 URL 文件,但是不可以解压。比如
ADD https://mirrors.aliyun.com/centos-vault/6.9/os/x86_64/Packages/edac-utils-devel-0.9-16.el6.x86_64.rpm /tmp/ -
制作镜像
docker build -t "wys/centos69_sshd_lamp_bbs" ./
- 执行失败,查看错误信息。可以看到是连接数据库失败。
---> d3652e0f7ff8
Removing intermediate container 872b4485d50f
Step 4/11 : RUN mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database discuz charset utf8;"
---> Running in adefbb34d25d
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)
The command '/bin/sh -c mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database discuz charset utf8;"' returned a non-zero code: 1
- 登录执行失败的上一步的容器,查看错误原因
docker container run -it --rm d3652e0f7ff8
/etc/init.d/mysqld start -- 正常启动
mysql -- 可以正常启动
/bin/sh -c mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database discuz charset utf8;" -- 从出错的命令我们可以看到是 /bin/bash 不能执行 mysql 命令
- 解决方案一:把这几条命令放到脚本中,执行脚本
mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database discuz charset utf8;"
- 解决方案二:把这个命令放在
init.sh脚本中。这个逻辑是正确的,授权命令只要在安装 discuz 之前做好了就可以了。
#!/bin/bash
/etc/init.d/mysqld start
/etc/init.d/httpd start
mysql -e "grant all on *.* to root@'%' identified by '123';grant all on *.* to discuz@'%' identified by '123';create database discuz charset utf8;"
/usr/sbin/sshd -D
- 重新编写 Dockerfile
# Centos6.9_sshd_LAMP
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 discuz.tar.gz /var/www/html/
ADD https://mirrors.aliyun.com/centos-vault/6.9/os/x86_64/Packages/edac-utils-devel-0.9-16.el6.x86_64.rpm /tmp/
EXPOSE 22
EXPOSE 80
EXPOSE 3306
CMD ["/bin/bash", "/init.sh"]
- 制作镜像
docker build -t "wys/centos69_sshd_lamp_bbs" ./
- 查看镜像
[root@VM-0-3-centos lamp]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
wys/centos69_sshd_lamp_bbs latest 01e9ef53a65f 15 seconds ago 465 MB
- 启动容器
docker container run -d -p 80 -p 3306 -p 22 wys/centos69_sshd_lamp_bbs:latest
- 查看容器
[root@VM-0-3-centos lamp]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7619cf31cb08 wys/centos69_sshd_lamp_bbs:latest "/bin/bash /init.sh" 50 seconds ago Up 49 seconds 0.0.0.0:32773->22/tcp, 0.0.0.0:32772->80/tcp, 0.0.0.0:32771->3306/tcp elastic_mcclintock
- 测试访问,使用 80 对应的 32772 端口
http://82.156.85.205:32772/upload/install/
- 安装失败了,发现还是权限的问题,登录容器授权 777,刷新重新安装
docker container exec -it 7619cf31cb08 /bin/bash
chmod -R 777 /var/www/html/
- 检查 copy ADD 是否成功。能正常执行 copy add 肯定是正常的。再看一下 /tmp 目录下有没有对应文件就好了
ssh 172.17.0.4
[root@7619cf31cb08 ~]# cd /tmp/
[root@7619cf31cb08 tmp]# ll
total 56
-rw-r--r-- 5 root root 1991 Mar 28 2017 CentOS-Base.repo
-rw-r--r-- 5 root root 647 Mar 28 2017 CentOS-Debuginfo.repo
-rw-r--r-- 5 root root 630 Mar 28 2017 CentOS-Media.repo
-rw-r--r-- 5 root root 7989 Mar 28 2017 CentOS-Vault.repo
-rw-r--r-- 5 root root 289 Mar 28 2017 CentOS-fasttrack.repo
-rw------- 11 root root 19035 Apr 6 2017 anaconda-post.log
-rw------- 1 root root 8680 Jul 24 2015 edac-utils-devel-0.9-16.el6.x86_64.rpm
-rw------- 11 root root 0 Apr 6 2017 yum.log
8.3 VOLUME 指令介绍
VOLUME 指令的作用是在镜像中创建挂载点。
该指令与 -V 的区别是,通过 VOLUME 指令 创建的挂载点,无法指定主机上对应的目录,是自动生成的。
生成的挂载文件是在 /var/lib/docker/volumes/ 目录下,文件名随机生成。
我们来试验一下。
- 编写 Dockerfile,挂载两个目录
# Centos6.9_sshd_LAMP
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 discuz.tar.gz /var/www/html/
ADD https://mirrors.aliyun.com/centos-vault/6.9/os/x86_64/Packages/edac-utils-devel-0.9-16.el6.x86_64.rpm /tmp/
VOLUME ["/var/www/html","data/mysql/data"]
EXPOSE 22
EXPOSE 80
EXPOSE 3306
CMD ["/bin/bash", "/init.sh"]
- 制作镜像
docker build -t "wys/centos69_sshd_lamp_volume" ./
- 查看镜像
[root@VM-0-3-centos lamp]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
wys/centos69_sshd_lamp_volume latest 40c5b1598239 6 seconds ago 465 MB
- 使用镜像启动容器
docker container run -d -p 80 -p 3306 -p 22 wys/centos69_sshd_lamp_volume:latest
- 查看容器
[root@VM-0-3-centos lamp]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7c2d98b62372 wys/centos69_sshd_lamp_volume:latest "/bin/bash /init.sh" 7 seconds ago Up 6 seconds 0.0.0.0:32776->22/tcp, 0.0.0.0:32775->80/tcp, 0.0.0.0:32774->3306/tcp priceless_meitner
adefbb34d25d d3652e0f7ff8 "/bin/sh -c 'mysql..." 3 hours ago Exited (1) 3 hours ago confident_hopper
- 测试连接
echo "" > ~/.ssh/known_hosts
ssh 172.17.0.2
- 去
/var/lib/docker/volumes/目录查看挂载文件。
root@VM-0-3-centos ~]# cd /var/lib/docker/volumes/
[root@VM-0-3-centos volumes]# ll
总用量 32
drwxr-xr-x 3 root root 4096 3月 3 21:45 015f35f12c910e38fa4064f39fad82730695f02ab3ba4941bfa44b59b9fac817
drwxr-xr-x 3 root root 4096 3月 3 21:45 fae15a2b1fc8105b02634252eca97d3d81e79e37179e4f63fd721fd8bc8f6b4a
-rw------- 1 root root 32768 3月 3 21:45 metadata.db
8.4 WORKDIR 指令介绍
WORKDIR 命令的作用是在 docker 中进入某个目录,相当于 cd。
存在的缺点是,当我们使用 WORKDIR 进入某个目录后,后续的所有操作都在这个目录下,如果我们想进入其他目录,只能使用绝对路径。
平时我们可以使用 cd 代替
8.5 ENV 指令介绍
ENV 指令就是用来给一串指令定义别名的,类似变量。在 Dockerfile 中就可以使用这个变量了。
我们来试验一下。
- 编写 Dockerfile
# Centos6.9_sshd_LAMP
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 /
ENV CODE_DIR="/var/www/html/"
ENV DATA_DIR="/data/mysql/data"
ADD discuz.tar.gz ${CODE_DIR}
ADD https://mirrors.aliyun.com/centos-vault/6.9/os/x86_64/Packages/edac-utils-devel-0.9-16.el6.x86_64.rpm /tmp/
VOLUME ["${CODE_DIR}","${DATA_DIR}"]
EXPOSE 22
EXPOSE 80
EXPOSE 3306
CMD ["/bin/bash", "/init.sh"]
- 制作镜像
docker build -t "wys/centos69_sshd_lamp_env" ./
- 查看镜像
[root@VM-0-3-centos lamp]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
wys/centos69_sshd_lamp_env latest 111bd2d14042 7 seconds ago 465 MB
- 使用镜像启动容器
docker container run -d -p 80 -p 3306 -p 22 wys/centos69_sshd_lamp_env:latest
- 查看容器
[root@VM-0-3-centos lamp]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4f6fda3d493f wys/centos69_sshd_lamp_env:latest "/bin/bash /init.sh" 12 seconds ago Up 10 seconds 0.0.0.0:32779->22/tcp, 0.0.0.0:32778->80/tcp, 0.0.0.0:32777->3306/tcp agitated_knuth
adefbb34d25d d3652e0f7ff8 "/bin/sh -c 'mysql..." 5 hours ago Exited (1) 5 hours ago confident_hopper
- 测试连接
echo "" > ~/.ssh/known_hosts
ssh 172.17.0.2
- 进入容器查看文件是否存在
[root@4f6fda3d493f ~]# cd /var/www/html/
[root@4f6fda3d493f html]# ll
total 12
drwxr-xr-x 2 root root 4096 Mar 3 15:08 readme
drwxr-xr-x 12 root root 4096 Mar 3 15:08 upload
drwxr-xr-x 4 root root 4096 Mar 3 15:08 utility
8.6 ENTRYPOINT 指令介绍
ENTRYPOINT 指令同 CMD 类似,也是出现在 Dockerfile 最后面的指令。
作用:在构建容器时最后运行的命令。
和 CMD 区别:使用 CMD 时,如果容器启动最后跟着一条命令,CMD 中的命令就会被这一条命令所替换,ENTRYPOINT 则不会被替换。
ENTRYPOINT 可以防止在启动容器是,第一进程被手工输入的命令被替换掉,防止容器秒起秒关。
我们来试验一下:
docker container run -d -p 80 -p 3306 -p 22 wys/centos69_sshd_lamp_env:latest /bin/bash
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cd8734412370 wys/centos69_sshd_lamp_env:latest "/bin/bash" About a minute ago Exited (0) About a minute ago mystifying_fermi
我们再使用 ENTRYPOINT 指令看一下。
- 编写 Dockerfile
# Centos6.9_sshd_LAMP
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 /
ENV CODE_DIR="/var/www/html/"
ENV DATA_DIR="/data/mysql/data"
ADD discuz.tar.gz ${CODE_DIR}
ADD https://mirrors.aliyun.com/centos-vault/6.9/os/x86_64/Packages/edac-utils-devel-0.9-16.el6.x86_64.rpm /tmp/
VOLUME ["${CODE_DIR}","${DATA_DIR}"]
EXPOSE 22
EXPOSE 80
EXPOSE 3306
# CMD ["/bin/bash", "/init.sh"]
ENTRYPOINT ["/bin/bash", "/init.sh"]
- 制作镜像
docker build -t "wys/centos69_sshd_lamp_entrypoint" ./
- 查看镜像
[root@VM-0-3-centos lamp]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
wys/centos69_sshd_lamp_entrypoint latest 89b4cec375b8 13 seconds ago 465 MB
- 使用镜像启动容器
docker container run -d -p 80 -p 3306 -p 22 wys/centos69_sshd_lamp_entrypoint:latest /bin/bash
- 查看容器,发现仍在启动中
[root@VM-0-3-centos lamp]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
40b0448358f7 wys/centos69_sshd_lamp_entrypoint:latest "/bin/bash /init.s..." 6 seconds ago Up 5 seconds 0.0.0.0:32791->22/tcp, 0.0.0.0:32790->80/tcp, 0.0.0.0:32789->3306/tcp vibrant_joliot