续我的上篇博文:https://mp.csdn.net/postedit/88645414
1.镜像的简介
在使用DockerFile定制镜像之前,我们先来了解一下镜像的构成:镜像是容器的基础,每次执行docker run命令的时候都会指定哪个镜像作为容器运行的基础。在之前的例字中,我们使用的镜像都是来自Docker Hub的镜像。直接使用这些镜像为基础运行容器可以一定程度上满足我们的需求,可是当这些镜像都无法直接满足需求时,我们就需要定制镜像!
2.Dockerfile的简介
使用Dockerfile可以允许用户创建自定义的镜像
Dockerfile一般由一条条语句组成,并支持以 # 开头的注释行
一般来说Dockerfile分为四部分
- 基础镜像信息:以哪个镜像作为基础进行制作,用法是FROM基础镜像名称
- 维护者信息:需要写下该Dockerfile编写人的姓名或邮箱,用法是MANITAINER 名称/邮箱
- 镜像操作指令:对基础镜像要进行的改造命令,比如安装新的软件,进行哪些特殊配置等,常见的是RUN命令
- 容器启动时执行指令:当基于该镜像的容器启动时需要执行哪些命令,常见的是CMD命令或ENTRYPOINT
1.selinux和firewalld状态为disabled
2.各主机信息如下:
主机 | ip |
---|---|
server1(Docker) | 172.25.83.1 |
3.在server1上安装docker,并启动docker服务
首先在官网上下载如下的软件包及依赖包:
其次,使用yum源进行安装即可
[root@server1 ~]# yum install * -y
最后,启动docker服务即可
[root@server1 ~]# systemctl start docker
4.在server1上导入rhel7镜像和busybox,为后面的实验做准备
首先在网上下载rhel7镜像对应的tar包:rhel7.tar;busybox镜像对应的tar包:busybox.tar
[root@server1 ~]# ls
busybox.tar rhel7.tar
[root@server1 ~]# docker load -i rhel7.tar #导入rhel7镜像
[root@server1 ~]# docker load -i busybox.tar #导入busybox镜像
5.在server1上创建目录/mnt/docker,为后续的实验做准备
[root@server1 ~]# mkdir /mnt/docker
1、编写支持apache的Dockerfile
[root@server1 ~]# cd /mnt/docker/
[root@server1 docker]# mkdir apache
[root@server1 docker]# cd apache
[root@server1 apache]# vim Dockerfile
FROM rhel7 #指定基础镜像(这里基础镜像选用rhel7的原因是rhel7镜像中可以配置yum源;而ubuntu镜像中不能配置yum源)
MAINTAINER [email protected] #作者信息(可选)
ENV HOSRNAME server1 #设定容器主机名(可选)
EXPOSE 80 #暴露容器端口
COPY dvd.repo /etc/yum.repos.d/dvd.repo #复制本地文件到容器中(因为下面要安装软件,所以必须阿先把yum源搭建好)
RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all #镜像操作命令(这里指安装httpd软件的命令)
CMD ["/usr/sbin/httpd","-D","FOREGROUND"] #镜像启动命令(这里指启动httpd服务的命令)
注:rpmdb命令用于初始化和重建rpm数据库
--initdb:初始化RPM数据库;
--rebuilddb:从已安装的包头文件,反向重建RPM数据库。
注:yum clean all可有可无,是用来清空yum缓存,减小镜像大小的
值的注意的是:Dockerfile文件中的引号,必须是双引号,而不能是单引号。
httpd服务启动命令编写的来源(因为物理机和虚拟机系统都是rhel7.3版本的,所以这里可在物理机操作):在物理机敲命令"ps aux"
2、编写dvd.repo文件
[root@server1 apache]# vim dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.83.83/rhel7.3
gpgcheck=0
enabled=1
3、构建镜像
[root@server1 apache]# docker build -t rhel7:apache . #读取当前目录下的Dockerfile文件,创建镜像rhel7:apache。
#值的注意的是:最好不要在根目录下进行操作。否则,创建镜像的过程将会相当慢
4、测试apache
[root@server1 apache]# docker run -d --name vm1 rhel7:apache #创建并运行vm1容器
[root@server1 apache]# vim index.html #编写测试页
www.xin.com
[root@server1 apache]# docker container cp index.html vm1:/var/www/html/
1、修改支持apache的Dockerfile
[root@server1 apache]# vim Dockerfile
FROM rhel7
MAINTAINER [email protected]
ENV HOSRNAME server1
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all
VOLUME ["/var/www/html"] #设定数据卷为/var/www/html
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
2、沿用上面的dvd.repo文件
3、构建新的镜像
[root@server1 apache]# docker build -t rhel7:apache1 .
4、测试apache(当然也可以将index.html文件复制到容器vm2的/var/www/html目录中)
[root@server1 apache]# docker run -d --name vm2 rhel7:apache1 #创建并运行vm2容器
[root@server1 apache]# cd /var/lib/docker/volumes/e4ab2e09e2dc48e5c2a861b39090d0fe915909566c34ee1a110e39400f330b88/_data #下面图片看到的volume的地址
[root@server1 e4ab2e09e2dc48e5c2a861b39090d0fe915909566c34ee1a110e39400f330b88_data]# vim index.html
music.xin.com
1、沿用数据卷用法一的Dockerfile
2、沿用上面的dvd.repo文件
3、沿用数据卷用法一的镜像
4、测试apache(当然也可以将index.html文件复制到容器vm2的/var/www/html目录中)
[root@server1 apache]# docker run -d --name vm3 -v /mnt/docker/apache/:/var/www/html:ro rhel7:apache1 #创建并运行vm3容器,并将本地主机的/mnt/docker/apache目录(该目录下有index.html)以只读的模式(默认是可读可写模式)挂载到容器vm3的/var/www/html目录下
1、编写支持ssh的Dockerfile
[root@server1 docker]# mkdir ssh
[root@server1 docker]# cd ssh/
[root@server1 ssh]# vim Dockerfile
FROM rhel7
MAINTAINER [email protected] #(可选)
ENV HOSRNAME server2 #(可选)
EXPOSE 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y openssh-server openssh-clients && yum clean all && ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -q -N "" && ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -q -N "" && ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -q -N "" && echo root:xjj | chpasswd
CMD ["/usr/sbin/sshd","-D"]
sshd服务启动命令编写的来源(因为物理机和虚拟机系统都是rhel7.3版本的,所以这里可在物理机操作):在物理机敲命令"ps aux"
2、编写dvd.repo文件
[root@server1 ssh]# vim dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.83.83/rhel7.3
gpgcheck=0
enabled=1
3、构建镜像
[root@server1 apache]# docker build -t rhel7:ssh .
4、测试sshd服务
[root@server1 ssh]# docker run -d --name vm4 -p 2222:22 rhel7:ssh #-p表示端口映射,因为真实的22端口是打开的,所以这里要做一个端口映射
[root@foundation83 images]# ssh -p 2222 [email protected] #在物理机上测试sshd服务
当然,测试sshd服务,也可以在server1上进行测试(ssh -p 2222 [email protected]或ssh [email protected])
CMD 如果只有一个命令,那如果我们需要运行多个服务怎么办呢?
最好的办法是分别在不同的容器中运行,通过 link 进行连接,比如先前实验中用到的apache、ssh 容器。如果一定要在一个容器中运行多个服务可以考虑用 Supervisord 来进行进程管理,方式就是将多个启动命令放入到一个启动脚本中。
前期准备:
在网上下载rpm包:supervisor-3.1.4-1.el7.noarch.rpm和 python-meld3-0.6.10-1.el7.x86_64.rpm(supervisord的依赖包),并将其放在下面建好的目录/mnt/docker/supervisord目录下,以便安装该rpm包。
1、编写supervisord.conf文件
[root@server1 docker]# mkdir supervisord
[root@server1 docker]# cd supervisord/
[root@server1 supervisord]# vim supervisord.conf
[supervisord]
nodaemon=true #表示有后台程序
[program:httpd]
command=/usr/sbin/httpd
[program:ssh]
command=/usr/sbin/sshd -D
2、编写apache测试页
[root@server1 supervisord]# vim index.html #编写测试页
music.xin.com
3、编写支持supervisord的Dockerfile(同时运行apache、sshd服务)
[root@server1 supervisord]# vim Dockerfile
FROM rhel7
MAINTAINER [email protected] #(可选)
ENV HOSRNAME server3 #(可选)
EXPOSE 80 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD supervisor-3.1.4-1.el7.noarch.rpm /mnt #将所在目录下的supervisor-3.1.4-1.el7.noarch.rpm拷贝到容器内的/mnt目录下
ADD python-meld3-0.6.10-1.el7.x86_64.rpm /mnt #将所在目录下的python-meld3-0.6.10-1.el7.x86_64.rpm拷贝到容器内的/mnt目录下
WORKDIR /mnt #进入容器内的/mnt目录下
RUN rpmdb --rebuilddb && yum install -y openssh-server openssh-clients httpd supervisor-3.1.4-1.el7.noarch.rpm python-meld3-0.6.10-1.el7.x86_64.rpm && yum clean all && ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -q -N "" && ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -q -N "" && ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -q -N "" && echo root:xjj | chpasswd
COPY supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord"]
4、编写dvd.repo文件
[root@server1 supervisord]# vim dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.83.83/rhel7.3
gpgcheck=0
enabled=1
5、构建镜像
[root@server1 supervisord]# docker build -t rhel7:supervisord .
6、测试
[root@server1 supervisord]# docker run -d --name vm5 -p 8080:80 -p 2223:22 -v /mnt/docker/supervisord/:/var/www/html rhel7:supervisord
[root@server1 apache]# docker inspect vm5 | grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.6",
"IPAddress": "172.17.0.6",
[root@foundation83 Desktop]# ssh -p 2223 [email protected] #在物理机远程连接
The authenticity of host '[172.25.83.1]:2223 ([172.25.83.1]:2223)' can't be established.
ECDSA key fingerprint is 2f:d0:44:3f:5e:20:1b:d5:fe:c3:f1:0a:cd:bb:7a:47.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[172.25.83.1]:2223' (ECDSA) to the list of known hosts.
[email protected]'s password: #输入密码:xjj(Dockerfile文件中指定的密码)
Last login: Tue Mar 19 23:13:57 2019 from 172.17.0.1
-bash-4.2# ls
anaconda-ks.cfg
[root@foundation83 Desktop]# curl 172.25.83.1:8080
music.xin.com
当然,测试apache服务,也可以在server1上进行测试(curl 172.25.83.1:8080或curl 172.17.0.6)
当然,测试sshd服务,也可以在server1上进行测试(ssh -p 2223 [email protected]或ssh [email protected])
1、编写支持busybox的Dockerfile
[root@server1 docker]# mkdir busybox
[root@server1 docker]# cd busybox
[root@server1 busybox]# vim Dockerfile
FROM busybox
ENV name world
CMD echo "hello,$name" #CMD命令有三种写法
2、编写dvd.repo文件
[root@server1 busybox]# vim dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.83.83/rhel7.3
gpgcheck=0
enabled=1
3、构建镜像
[root@server1 busybox]# docker build -t busybox:v1 .
4、测试busybox服务
[root@server1 busybox]# docker run --rm busybox:v1 #用busybox:v1镜像创建容器,并运行,运行完成之后,立即删除
1、编写支持busybox的Dockerfile
[root@server1 docker]# mkdir busybox
[root@server1 docker]# cd busybox
[root@server1 busybox]# vim Dockerfile
FROM busybox
ENV name world
CMD ["/bin/echo","hello,$name"]
2、沿用上面的dvd.repo文件
3、构建镜像
[root@server1 busybox]# docker build -t busybox:v2 .
4、测试busybox服务
[root@server1 busybox]# docker run --rm busybox:v2 #用busybox:v2镜像创建容器,并运行,运行完成之后,立即删除
我们可以看到,上面的第二种CMD的写法,不进行变量的解析。
1、编写支持busybox的Dockerfile
[root@server1 docker]# mkdir busybox
[root@server1 docker]# cd busybox
[root@server1 busybox]# vim Dockerfile
FROM busybox
ENV name world
CMD ["/bin/sh","-c","echo hello,$name"]
2、沿用上面的dvd.repo文件
3、构建镜像
[root@server1 busybox]# docker build -t busybox:v3 .
4、测试busybox服务
[root@server1 busybox]# docker run --rm busybox:v3 #用busybox:v3镜像创建容器,并运行,运行完成之后,立即删除
1、编写支持busybox的Dockerfile
[root@server1 docker]# mkdir busybox
[root@server1 docker]# cd busybox
[root@server1 busybox]# vim Dockerfile
FROM busybox
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]
2、沿用上面的dvd.repo文件
3、构建镜像
[root@server1 busybox]# docker build -t busybox:v4 .
4、测试busybox服务
[root@server1 busybox]# docker run --rm busybox:v4 #用busybox:v4镜像创建容器,并运行,运行完成之后,立即删除
第二张图片表明CMD命令是会被docker run提供的参数覆盖的;而ENTRYPOINT命令是不会被docker run提供的参数覆盖的。
前期准备:
在网上下载压缩包:nginx-1.15.8.tar.gz,并将其放在下面建好的目录/mnt/docker/nginx目录下,以便将其放在容器内。
1、编写支持nginx的Dockerfile
[root@server1 ~]# cd /mnt/docker/
[root@server1 docker]# mkdir nginx
[root@server1 docker]# cd nginx
[root@server1 nginx]# vim Dockerfile
FROM rhel7
MAINTAINER [email protected]
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
nginx服务启动命令编写的来源:
2、编写dvd.repo文件
[root@server1 apache]# vim dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.83.83/rhel7.3
gpgcheck=0
enabled=1
3、构建镜像
[root@server1 nginx]# docker build -t rhel7:nginx .
4、测试nginx
[root@server1 nginx]# docker run -d --name vm6 rhel7:nginx #创建并运行vm6容器
[root@server1 nginx]# cd /var/lib/docker/volumes/112c2aace756e75dd0415d76e25ffd2824e5a13ac03783513663524e3e0c4b8f/_data #该数据卷的目录来源于下面的图片(查看vm6容器的关于volume的详情)
[root@server1 _data]# ls #值的注意的是:在默认的数据卷中,会有相应的数据。(这是由nginx基础镜像决定的)。
50x.html index.html
[root@server1 _data]# vim index.html
news.xin.com
1、编写支持nginx的Dockerfile
[root@server1 nginx]# vim Dockerfile
FROM rhel7
MAINTAINER [email protected]
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make &> /dev/null && yum clean all
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx &> /dev/null
RUN make &> /dev/null
RUN make install &> /dev/null
RUN rm -rf /mnt/nginx-1.15.8
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
2、沿用上面的dvd.repo文件
3、构建镜像
[root@server1 nginx]# docker build -t rhel7:nginx1 .
我们可以看到这次生成的镜像rhel7:nginx1的大小为252M。
1、编写支持nginx的Dockerfile
[root@server1 nginx]# vim Dockerfile
FROM rhel7
MAINTAINER [email protected]
EXPOSE 80
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make &> /dev/null && yum clean all && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -rf /mnt/nginx-1.15.8
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
2、沿用上面的dvd.repo文件
3、构建镜像
[root@server1 nginx]# docker build -t rhel7:nginx2 .
我们可以看到这次生成的镜像rhel7:nginx2的大小为250M。
1、编写支持nginx的Dockerfile
[root@server1 nginx]# vim Dockerfile
FROM rhel7 as build
MAINTAINER [email protected]
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make &> /dev/null && yum clean all && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -rf /mnt/nginx-1.15.8
FROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
多阶段构建镜像是如何工作的呢?
第二条FROM指令以rhel7镜像作为基础开始新的建造阶段。COPY --from=build 这一行将前一个阶段(FROM rhel7 as build)产生的构件复制到这个新的阶段。任何中间的构件都被留在哪里,而不会保存到最终的镜像中。
2、沿用上面的dvd.repo文件
3、构建镜像
[root@server1 nginx]# docker build -t rhel7:nginx3 .
我们可以看到这次生成的镜像rhel7:nginx3的大小为141M。
4、构建的镜像那么小,那它到底能不能用呢,我们来测试一下:
[root@server1 nginx]# docker run -d --name vm7 rhel7:nginx3 #创建并运行vm7容器
[root@server1 nginx]# cd /var/lib/docker/volumes/bd729554911d6b2a8d67bcbb370161c2b5669c3ef69a0d8b704c0b9f8f969bf8/_data 该数据卷的目录来源于下面的图片(查看vm7容器的关于volume的详情)
[root@server1 _data]# ls #值的注意的是:在默认的数据卷中,会有相应的数据(这是由nginx基础镜像决定的)。
50x.html index.html
[root@server1 _data]# vim index.html
haha.xin.com
1、编写支持nginx的Dockerfile
[root@server1 nginx]# vim Dockerfile
FROM nginx as base
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG Asia/Shanghai
RUN mkdir -p /opt/var/cache/nginx && \
cp -a --parents /usr/lib/nginx /opt && \
cp -a --parents /usr/share/nginx /opt && \
cp -a --parents /var/log/nginx /opt && \
cp -aL --parents /var/run /opt && \
cp -a --parents /etc/nginx /opt && \
cp -a --parents /etc/passwd /opt && \
cp -a --parents /etc/group /opt && \
cp -a --parents /usr/sbin/nginx /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime
FROM gcr.io/distroless/base
COPY --from=base /opt /
EXPOSE 80
ENTRYPOINT ["nginx","-g","daemon off;"]
2、沿用上面的dvd.repo文件
3、在网上下载distorless.tar文件,并将其导入到镜像中
[root@server1 ~]# docker load -i distroless.tar
4、构建镜像
[root@server1 nginx]# docker build -t rhel7:nginx4 .
我们可以看到这次生成的镜像rhel7:nginx4的大小为23.6M。
4、构建的镜像那么小,那它到底能不能用呢,我们来测试一下:
[root@server1 nginx]# docker run -d --name vm8 rhel7:nginx4 #创建并运行vm7容器
[root@server1 nginx]# vim index.html
www.xin.com
[root@server1 nginx]# docker cp index.html vm8:/usr/share/nginx/html