欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT

程序员文章站 2024-01-26 15:04:04
...

Dockfile简介

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。

  Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
  

Dockerfile 常用指令:

1. 指定容器运行的用户

该用户将作为后续的 RUN 命令执行的用户。这个命令本实验不需要,但在一些需要指定用
户来运行的应用部署时非常关键,比如提供 hadoop 服务的容器通常会使用 hadoop 用户来启
动服务。
命令使用方式,例如使用 shiyanlou 用户来执行后续命令:
USER shiyanlou

2. 指定后续命令的执行目录

由于我们需要运行的是一个静态网站,将启动后的工作目录切换到/var/www/html 目录:WORKDIR /var/www/html

3. 对外连接端口号

由于内部服务会启动 Web 服务,我们需要把对应的 80 端口暴露出来,可以提供给容器间互联使用,可以使用 EXPOSE 命令。
在镜像操作部分增加下面一句:
EXPOSE 80

4. 设置容器主机名

ENV 命令能够对容器内的环境变量进行设置:
ENV HOSTNAME sevrer1.example.com

5. 向镜像中增加文件

向镜像中添加文件有两种命令:COPY 和 ADD。
COPY 命令可以复制本地文件夹到镜像中:
COPY website /var/www/html
ADD 命令支持添加本地的 tar 压缩包到容器中指定目录,压缩包会被自动解压为目录,也
可以自动下载 URL 并拷贝到镜像,例如:
ADD html.tar /var/www
ADD http://www.westos.org/html.tar /var/www
根据实验需求,我们把需要的一个网站放到镜像里,需要把一个 tar 包添加到 apache 的
/var/www 目录下,因此选择使用 ADD 命令:
ADD html.tar /var/www

6. CMD 与 ENTRYPOINT(下面有实验说明)

ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与
CMD 的 区 别 是 不 可 以 被 docker run 覆 盖 , 会 把 docker run 后 面 的 参 数 当 作 传 递 给
ENTRYPOINT 指令的参数。Dockerfile 中只能指定一个 ENTRYPOINT,如果指定了很多,
只 有 最 后 一 个 有 效 。 docker run 命 令 的 -entrypoint 参 数 可 以 把 指 定 的 参 数 继 续 传 递 给
ENTRYPOINT。在本实验中两种方式都可以选择。

7. 挂载数据卷

将 apache 访问的日志数据存储到宿主机可以访问的数据卷中:
VOLUME [“/var/log/apche2”]

8. 设置容器内的环境变量

使用 ENV 设置一些 apache 启动的环境变量:
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apche2
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOCK_DIR /var/lock/apche2

以下为Dockfile的3个实例

注:创建镜像过程中如果有错想重新创建,可以删除然后重新创建

删除镜像
[root@foundation10 docker]# docker rmi rhel7:v3
查看是否删除
[root@foundation10 docker]# docker images

1、Dockerfile 编写:Web服务

[aaa@qq.com ns]# cd /tmp/docker/
[aaa@qq.com docker]# vim Dockerfile
FROM rhel7                         ##指定基础镜像
ENV HOSTNAME server1               ##设定容器主机名
MAINTAINER 573245320@qq.com        ##作者信息
EXPOSE 80                          ##暴露容器端口
COPY dvd.repo /etc/yum.repos.d/dvd.repo   ##复制yum源,不然无法下载
RUN rpmdb --rebuilddb && yum install -y httpd && yum clean all  ##镜像操作命令
VOLUME ["/var/www/html"]           ##挂载数据卷到此目录下
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]  ##镜像启动命令,默认只能启动一条

创建镜像rhel7:v1

[root@foundation10 docker]# docker build -t rhel7:v1 .

查看镜像rhel7:v1

查看本地镜像
[root@foundation10 docker]# docker images rhel7
查看rhel:v1信息
[root@foundation10 docker]# docker history rhel7:v1

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT
检验:
运行docker挂载数据卷到新创建的容器上

[root@foundation10 docker]# docker run -d --name vm3 -v /tmp/docker/web:/var/www/html rhel7:v1
查看vm3的IP
[root@foundation10 docker]# docker inspect vm3
浏览器访问172.17.0.3

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT

2、Dockerfile 自启动 SSH 服务

先打开另一个Shell连接本机,将要写入Dockerfile的指令执行一遍,将遇到的问题解决,无误后再写入Dockerfile

[aaa@qq.com ~]# docker run -it --name vm1 rhel7 bash
bash-4.2# yum install -y openssh-server openssh-clients
bash-4.2# ls -l  /usr/sbin/sshd
执行提示没有钥匙
bash-4.2# /usr/sbin/sshd
创建钥匙
bash-4.2# ssh-****** -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N ""
bash-4.2# ssh-****** -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N ""
bash-4.2# ssh-****** -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
bash-4.2# /usr/sbin/sshd
bash-4.2# ssh localhost
修改密码
bash-4.2# echo root:westos | chpasswd   
bash-4.2# ssh localhost
bash-4.2# logout

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT
编写Dockerfile:自启动 SSH 服务

[root@foundation10 docker]# mkdir ssh
[root@foundation10 docker]# cp Dockerfile ssh/
[root@foundation10 docker]# cp dvd.repo ssh/
[root@foundation10 docker]# cd ssh/
[root@foundation10 ssh]# vim Dockerfile
FROM rhel7
ENV HOSTNAME server2
MAINTAINER 573245320@qq.com
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-****** -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-****** -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-****** -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
CMD ["/usr/sbin/sshd", "-D"]

创建镜像rhel7:v2

[root@foundation10 ssh]# docker build -t rhel7:v2 .
查看本地镜像
[root@foundation10 ssh]# docker images rhel7

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT
检验

运行docker
[root@foundation10 ssh]# docker run -d --name vm4 rhel7:v2
查看运行的docker
[root@foundation10 ssh]# docker ps
检验
[root@foundation10 ssh]# ssh aaa@qq.com
-bash-4.2# logout

3、Dockerfile 在镜像里封装2个应用,将以上2个服务结合

运行容器

[root@foundation10 ~]# docker run -d --name vm1 nginx

编辑Dockerfile

将之前本机的Yum源配置发送至vm1的yum源目录下
[aaa@qq.com ~]# cd /tmp/docker
[aaa@qq.com docker]# docker cp dvd.repo vm1:/etc/yum.repo
编辑Dockerfile
[aaa@qq.com docker]# vim Dockerfile 
FROM rhel7
EXPOSE 80 22
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd openssh-server openssh-clients supervisor && yum clean all && ssh-****** -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-****** -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-****** -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
COPY supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord"]

随即编辑yum源文件,应用supervisor-3.1.3-3.el7.noarch.rpm

[aaa@qq.com docker]# vim dvd.repo 
[rhel7.3]
name=rhel7.3
baseurl=http://172.25.254.10/rhel7.3
gpgcheck=0

[docker]
name=docker
baseurl=http://172.25.254.10/pub/docker   ##本机存放supervisor-3.1.3-3.el7.noarch.rpm的目录
gpgcheck=0

编辑supervisord.conf 文件

[aaa@qq.com docker]# vim supervisord.conf 
[supervisord]
nodaemon=true

[program:sshd]
command=/usr/sbin/sshd -D

[program:httpd]
command=/usr/sbin/httpd

创建镜像、挂载运行

创建镜像rhel7:v3
[root@foundation10 docker]# docker build -t rhel7:v3 .
挂载运行
[root@foundation10 docker]# docker run -d --name vm1 -v /tmp/docker/web:/var/www/html rhel7:v3

检测:

查看IP
[root@foundation10 Desktop]# docker inspect vm1
查看是否有默认发布内容
[root@foundation10 docker]# curl 172.17.0.2
查看是否能连接
[root@foundation10 docker]# ssh -l root 172.17.0.2

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT
Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT

4、RUN CMD ENTRYPOINT的区别

ENTRYPOINT 容器启动后执行的命令,让容器执行表现的像一个可执行程序一样,与
CMD 的 区 别 是 不 可 以 被 docker run 覆 盖 , 会 把 docker run 后 面 的 参 数 当 作 传 递 给
ENTRYPOINT 指令的参数。Dockerfile 中只能指定一个 ENTRYPOINT,如果指定了很多,
只 有 最 后 一 个 有 效 。 docker run 命 令 的 -entrypoint 参 数 可 以 把 指 定 的 参 数 继 续 传 递
给ENTRYPOINT。在实验中两种方式都可以选择。

编辑Dockerfile测试

[root@foundation10 ~]# cd /tmp/docker/
[root@foundation10 docker]# mkdir test
[root@foundation10 docker]# cd test/
CMD容器启动时,docker run执行后可被覆盖
[root@foundation10 test]# vim Dockerfile
FROM rhel7
CMD echo "hello world!"
创建镜像
[root@foundation10 test]# docker build -t rhel7:v4 .   
运行镜像查看
[root@foundation10 test]# docker run --rm rhel7:v4
加参数运行查看
[root@foundation10 test]# docker run --rm rhel7:v4 westos
[root@foundation10 test]# docker run --rm rhel7:v4 echo westos
删除镜像
[root@foundation10 test]# docker rmi rhel7:v4

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT
以上操作在镜像删除后再重新编辑Dockfile,重新创建rhel7:v4,然后测试,测试完后再执行以上操作,只改变测试内容。以下是其他测试内容和结果:

ENTRYPOINT 容器启动后不可以被 docker run 覆盖
[aaa@qq.com test]# vim Dockerfile
FROM rhel7
ENTRYPOINT echo "hello world!"

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT

CMDENTRYPOINT结合时 CMDENT 传参
[root@foundation10 test]# vim Dockerfile
FROM rhel7
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT
ENTRYPOINT的2种表达方式:

[aaa@qq.com test]# vim Dockerfile
FROM rhel7
ENV name westos
ENTRYPOINT echo "hello $name"

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT

[root@foundation10 test]# vim Dockerfile
FROM rhel7
ENV name westos
ENTRYPOINT ["/bin/sh","-c","echo $name"]

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT

5、数据卷应用

如果-v后面不跟系统目录 容器会帮我们自动分配,挂载数据卷
把静态数据放进镜像 ,镜像挂载到容器使用
如果挂载数据到系统目录,那么数据来源于本地,现在是数据来源于镜像,但是是只读的

查看默认发布文件
[aaa@qq.com tmp]# cd /tmp/docker/web/
[aaa@qq.com web]# cat index.html 
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
<h1>www.westos.org</h1>
复制默认发布文件到新建的目录
[aaa@qq.com web]# cd ..
[aaa@qq.com docker]# cp web/index.html  test/
制作html.tar包
[aaa@qq.com docker]# cd test/
[aaa@qq.com test]# mkdir nginx
[aaa@qq.com test]# mkdir nginx/html
[aaa@qq.com test]# cp index.html nginx/html
[aaa@qq.com test]# tar cf html.tar nginx/ 
[aaa@qq.com test]# ls
Dockerfile  html.tar  nginx  index.html
解压tar包
[aaa@qq.com test]# tar tf html.tar 
nginx/
nginx/html/
nginx/html/index.html
编写Dockerfile
[root@foundation10 test]# vim Dockerfile 
FROM rhel7
COPY index.html /usr/share/nginx/html
VOLUME ["/usr/share/nginx/html"]
将前一个实验的rhel7:v4删除
[root@foundation10 test]# docker rmi rhel7:v4
创建镜像
[root@foundation10 test]# docker build -t  rhel7:v4 .
运行数据卷容器
[root@foundation10 test]# docker create --name vol rhel7:v4 bash
[root@foundation10 test]# docker run -d --name vm1 --volumes-from vol nginx
查看vm1的IP
[root@foundation10 test]# docker inspect vm1
                    "IPAddress": "172.17.0.2",
测试
[root@foundation10 test]# curl 172.17.0.2                

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT
测试结果与nginx发布内容相同

[root@foundation10 test]# cd /tmp/docker/test/nginx/html/
[root@foundation10 html]# cat index.html 

Dockerfile定制镜像、Dockerfile应用示例、CMD 与 ENTRYPOINT