Docker-Dockerfile构建学习 – 记忆角落

Docker-Dockerfile构建学习

/ 0评 / 0

Docker-Dockerfile构建学习

Dockerfile介绍

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

构建步骤分为:

  1. 编写一个dockerfile文件
  2. docker build构建成为一个镜像
  3. docker run 运行镜像
  4. docker pull 发布镜像(docker hub,阿里云镜像仓库等..)

Dockerfile 指令说明

images_6567790-fff25499e56d7295

指令 含义
FROM 镜像 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令
MAINTAINER 名字 说明新镜像的维护人信息,姓名+邮箱-->gljadmin@199604.com
RUN 命令 镜像构建时,执行的命令
CMD [“要运行的程序”,”参数1”,”参数2”] 指令启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只能最后一条被执行
ENTRYPOINT 类似CMD命令,指定容器启动时候,需要运行的命令,可追加
EXPOSE 端口号 容器需要暴露的端口号,docker run -P 时,会自动随机映射 EXPOSE 的端口
ENV 环境变量 变量值 设置一个环境变量的值,会被后面的RUN使用
ADD 源文件/目录 目标文件/目录 将源文件复制到目标文件,源文件要与Dockerfile位于相同目录中, 或者是一个URL
COPY 源文件/目录 目标文件/目录 将本地主机上的文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中
VOLUME [“目录”] 在容器中创建一个挂载点
USER 用户名/UID 指定运行容器时的用户
WORKDIR 路径 为后续的RUN、CMD、ENTRYPOINT指定 镜像工作目录路径
ONBUILD 命令 指定所生成的镜像作为一个基础镜像时所要运行的命令(是一个特殊的触发指令)
HEALTHCHECK 健康检查
SHELL SHELL 指令可以指定 RUN ENTRYPOINT CMD 指令的 shell,Linux 中默认为 ["/bin/sh", "-c"]

FROM 指定基础镜像

如:FROM nginx,就以nginx为基础构建.

Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。FROM scratch.

如果你以 scratch 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

MAINTAINER 指定维护者的信息

例子:

MAINTAINER glj<admin@199604.com>

RUN 镜像构建时的执行命令

RUN 指令用于制定docker build 过程中要运行的命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。其格式有两种:

shell 格式:

RUN <命令>,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 RUN 指令就是这种格式。

例子:

RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

exec 格式:

RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式。

例子:

RUN yum -y install vim

ENV 设置环境变量

格式有两种:

例子:

ENV JAVA_VERSION 1.8.0

例子:

ENV JAVA_VERSION=1.8.0 DEBUG=on NAME="GLJ"

这个指令很简单,就是设置环境变量而已

WORKDIR 指定工作目录

格式为 WORKDIR <工作目录路径>

例子:

WORKDIR /usr/local

COPY 复制文件

格式:

RUN 指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。

COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。

例子:

COPY index.html /usr/share/nginx/html/index.htm

ADD 扩展了的复制文件

ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。

比如:如果 <源路径> 为一个 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去。

如Centos 官网的Dockerfile就是如此:

FROM scratch
ADD centos-7-x86_64-docker.tar.xz 

Docker 官方要求,尽可能的使用 COPY,因为 COPY 的语义很明确

另外需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。

因此在 COPYADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD

CMD 容器启动需要运行的命令

CMD 指令的格式和 RUN 相似,也是两种格式,推荐使用第二种格式:

例子:

CMD echo $JAVA_VERSION

CMD echo "----end----"

例子:

CMD ["/bin/echo", "this is a echo docker"]

CMD 指令指定的程序可被 docker run命令行参数中指定要运行的程序所覆盖。

如你指定:

CMD ["/bin/echo", "this is a echo docker"]

build后运行(假设镜像名为mycentos):

docker run mycentos就会输出: this is a echo docker

但是,如; docker run -it mycentos /bin/bash,不再输出:this is a echo docker,因为CMD命令被/bin/bash覆盖了

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

ENTRYPOINT 容器启动需要运行的命令(入口点)

ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。

可以搭配 CMD命令使用:一般是变参才会使用CMD ,这里的 CMD 等于是在给ENTRYPOINT 传参,换句话说实际执行时,将变为:

<ENTRYPOINT> "<CMD>"

CMD+ENTRYPOINT的实例:

假设我们需要一个得知自己当前公网 IP 的镜像,那么可以先用 CMD 来实现:

FROM centos:7.9.2009
MAINTAINER glj<admin@199604.com>

ENV TARPATH /home
WORKDIR $TARPATH

RUN yum -y install curl

CMD [ "curl", "-s", "http://myip.ipip.net" ]

假如我们使用 docker build -t checkip:v1 . 来构建镜像的话,如果我们需要查询当前公网 IP.

只需要执行:

[root@gzbsc001 mycentos]# docker run -it checkip:v1
当前 IP:120.235.165.226  来自于:中国 广东 广州  移动

如果需要追加参数怎么办?那么只能CMD+ENTRYPOINT配合即可:

FROM centos:7.9.2009
MAINTAINER glj<admin@199604.com>

ENV TARPATH /home
WORKDIR $TARPATH

RUN yum -y install curl

CMD [ "-i" ]
ENTRYPOINT [ "curl", "-s", "http://myip.ipip.net" ]

我们使用 docker build -t checkip:v2 . 来构建镜像.这次我们再来执行:

[root@gzbsc001 mycentos]# docker images
REPOSITORY            TAG        IMAGE ID       CREATED         SIZE
checkip               v2         9c528482c01a   7 seconds ago   348MB
checkip               v1         b95f6f873e5c   7 minutes ago   348MB
nginx                 latest     04661cdce581   7 days ago      141MB
tomcat                9.0        43e421a14aec   3 weeks ago     680MB
mysql                 5.7        938b57d64674   4 weeks ago     448MB
centos                7.9.2009   eeb6ee3f44bd   2 months ago    204MB
portainer/portainer   latest     580c0e4e98b0   8 months ago    79.1MB
java                  8          d23bdf5b1b1b   4 years ago     643MB
[root@gzbsc001 mycentos]# 
[root@gzbsc001 mycentos]# 
[root@gzbsc001 mycentos]# docker run checkip:v2
HTTP/1.1 200 OK
Date: Wed, 17 Nov 2021 09:11:51 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 70
Connection: keep-alive
X-Shadow-Status: 200
X-Via-JSL: 1cf16e4,4f293cc,-
Set-Cookie: __jsluid_h=2144db3d81319385679383be3efd7fcd; max-age=31536000; path=/; HttpOnly
X-Cache: bypass

当前 IP:120.235.165.226  来自于:中国 广东 广州  移动

最最最简单的CMD+ENTRYPOINT 实例:

FROM centos

CMD ["p in cmd"]
ENTRYPOINT ["echo"]

注意:如果 Dockerfile 中如果存在多个ENTRYPOINT 指令,仅最后一个生效。

VOLUME 定义匿名卷

格式为:

例子:VOLUME [''/data1","/data2"]

例子:VOLUME /data1

在docker运行时,docker会创建一个匿名的volume,并将此volume绑定到容器的data1目录中,如果容器的/data1目录下已经有内容,则会将内容拷贝的volume中。也就是,Dockerfile中的VOLUME /data1docker run -v /data1 checkip的匿名挂载效果一样。

在启动容器 docker run 的时候,我们也可以通过 -v 参数修改挂载点。

EXPOSE 暴露端口

仅仅只是声明端口。

格式为 EXPOSE <端口1> [<端口2>...]

在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

USER 指定当前用户

用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。

格式:USER <用户名>[:<用户组>]

例子:

RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN [ "redis-server" ]

HEALTHCHECK 健康检查

HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12 引入的新指令。

格式:

HEALTHCHECK 支持下列选项:

  1. --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
  2. --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
  3. --retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。

HEALTHCHECK --interval=60s --timeout=40s --retries=5

HEALTHCHECKCMD, ENTRYPOINT 一样,HEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。

SHELL 指令

格式:SHELL ["executable", "parameters"]

SHELL 指令可以指定 RUN ENTRYPOINT CMD 指令的 shell,Linux 中默认为 ["/bin/sh", "-c"]

例子:

SHELL ["/bin/sh", "-cex"]
# /bin/sh -cex "nginx"
ENTRYPOINT nginx

SHELL ["/bin/sh", "-cex"]
# /bin/sh -cex "nginx"
CMD nginx

参考Dockerfie 官方文档:https://docs.docker.com/engine/reference/builder

可到Dockerfile 最佳实践文档:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ 练手实践...

发布自己的镜像到仓库中

DockerHub

1.登录docker login

[root@gzbsc001 mytomcat]# docker login --help

Usage:  docker login [OPTIONS] [SERVER]

Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username

[root@gzbsc001 mytomcat]# docker login -u glj17
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded


2.提交镜像

docker push :将本地的镜像上传到镜像仓库,要先登陆到镜像仓库

推送镜像的规范是: docker push 注册用户名/镜像名:[tag]

tag命令修改为规范的镜像:

docker tag dec02f4c1226 glj17/mynginx:1.21.4

[root@gzbsc001 mytomcat]# docker tag dec02f4c1226 glj17/mynginx:1.21.4 

[root@gzbsc001 mytomcat]# docker push glj17/mynginx:1.21.4
The push refers to repository [docker.io/glj17/mynginx]
eac18618a1e0: Pushed 
3f9029f7aeb1: Pushed 
36fdbc2fc6f3: Pushed 
663de1ca3bab: Pushed 
40c95c921670: Pushed 
b4e84b4eb3f3: Pushed 
394d004881a3: Pushed 
174f56854903: Mounted from library/centos 
1.21.4: digest: sha256:fc510ef8eb9483255386f2da07e4ddba04630ed2de85d9c8a39d4e0556b8b5b8 size: 1992

image-20211117192438184

Dockerfile实战

构建sshd镜像

[root@gzbsc001 tmp]# mkdir mysshd
[root@gzbsc001 tmp]# cd mysshd/
[root@gzbsc001 mysshd]# vim Dockerfile # 编写dockerfile文件

FROM centos:7.9.2009
MAINTAINER this is mysshd glj<admin@199604.com>
RUN yum -y update
RUN yum -y install openssh* net-tools lsof telnet passwd
RUN echo '123456!@#' | passwd --stdin root
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN sed -i '/^session\s\+required\s\+pam_loginuid.so/s/^/#/' /etc/pam.d/sshd
RUN mkdir -p /root/.ssh && chown root:root /root && chmod 700 /root/.ssh
EXPOSE 22
CMD ["/usr/sbin/sshd" , "-D"]

[root@gzbsc001 mysshd]# docker build -t mysshd:v1 .
[root@gzbsc001 mysshd]# docker images
REPOSITORY            TAG        IMAGE ID       CREATED             SIZE
mysshd                v1         677eca2f9c45   34 seconds ago      719MB

[root@gzbsc001 mysshd]# docker run -d -P mysshd:v1
724dcf29adba83c32add89b3f42a4287006900ec0540b52061eaa24fddcc1e75

[root@gzbsc001 mysshd]#  docker ps -a
CONTAINER ID   IMAGE             COMMAND                  CREATED             STATUS                         PORTS                                     NAMES
724dcf29adba   mysshd:v1         "/usr/sbin/sshd -D"      24 seconds ago      Up 24 seconds                  0.0.0.0:49156->22/tcp, :::49156->22/tcp   priceless_elbakyan


[root@gzbsc001 mysshd]# ssh 127.0.0.1 -p49156
The authenticity of host '[127.0.0.1]:49156 ([127.0.0.1]:49156)' can't be established.
RSA key fingerprint is SHA256:WfwbFngOT9C5dDkPhMTFUNZnuLiSuhf2qZI7hZlOU+M.
RSA key fingerprint is MD5:e5:17:10:32:8b:cb:8a:17:ca:18:2a:6a:93:4f:22:ad.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[127.0.0.1]:49156' (RSA) to the list of known hosts.
root@127.0.0.1's password: 
[root@724dcf29adba ~]# pwd
/root

构建Nginx镜像

[root@gzbsc001 tmp]# mkdir mynginx
[root@gzbsc001 tmp]# cd mynginx/

[root@gzbsc001 mynginx]# vim Dockerfile # 编写dockerfile文件
FROM centos:7.9.2009
MAINTAINER this is mynginx glj<admin@199604.com>
RUN yum install -y proc-devel gcc gcc-c++ zlib zlib-devel make openssl-devel wget
ADD nginx-1.21.4.tar.gz /usr/local/
WORKDIR /usr/local/nginx-1.21.4/
RUN ./configure --prefix=/usr/local/nginx && make && make install
EXPOSE 80
EXPOSE 443
RUN echo "daemon off;">>/usr/local/nginx/conf/nginx.conf
WORKDIR /root/nginx
COPY run.sh /run.sh
RUN chmod 755 /run.sh
CMD ["/run.sh"]

[root@gzbsc001 mynginx]# vim run.sh
#!/bin/bash
/usr/local/nginx/sbin/nginx   ##开启Nginx服务

[root@gzbsc001 mynginx]# wget http://nginx.org/download/nginx-1.21.4.tar.gz #下载nginx包

[root@gzbsc001 mynginx]# docker build -t mynginx:1.21.4 .   ##创建镜像
Successfully built dec02f4c1226
Successfully tagged mynginx:1.21.4

[root@gzbsc001 mynginx]# docker images
REPOSITORY            TAG        IMAGE ID       CREATED          SIZE
mynginx               1.21.4     dec02f4c1226   12 minutes ago   475MB

[root@gzbsc001 mynginx]# docker run -d -P mynginx:1.21.4
b84a7cb5893729971b4685edec75300a98e640b60853f4443db4acb37181228c

[root@gzbsc001 mynginx]# docker ps 
CONTAINER ID   IMAGE            COMMAND     CREATED         STATUS         PORTS                                                                                NAMES
b84a7cb58937   mynginx:1.21.4   "/run.sh"   5 seconds ago   Up 4 seconds   0.0.0.0:49158->80/tcp, :::49158->80/tcp, 0.0.0.0:49157->443/tcp, :::49157->443/tcp   gallant_matsumoto


image-20211117185139231

构建Tomcat镜像

[root@gzbsc001 tmp]# mkdir mytomcat
[root@gzbsc001 tmp]# cd mytomcat/

[root@gzbsc001 mytomcat]# vim Dockerfile # 编写dockerfile文件
FROM centos:7.9.2009
MAINTAINER this is mytomcat glj<admin@199604.com>
ADD jdk-8u301-linux-x64.tar.gz /usr/local
WORKDIR /usr/local
RUN mv jdk1.8.0_301 /usr/local/java
ENV JAVA_HOME /usr/local/java     ##设置环境变量
ENV JAVA_BIN /usr/local/java/bin
ENV JRE_HOME /usr/local/java/jre
ENV PATH $PATH:/usr/local/java/bin:/usr/local/java/jre/bin
ENV CLASSPATH /usr/local/java/jre/bin:/usr/local/java/lib:/usr/local/java/jre/lib/charsets.jar

ADD apache-tomcat-8.5.72.tar.gz /usr/local
WORKDIR /usr/local
RUN mv apache-tomcat-8.5.72 /usr/local/tomcat8

EXPOSE 8080
ENTRYPOINT ["/usr/local/tomcat8/bin/catalina.sh","run"]

#自行上传或者wget下载对应的包
[root@gzbsc001 mytomcat]# wget https://d6.injdk.cn/oraclejdk/8/jdk-8u301-linux-x64.tar.gz
[root@gzbsc001 mytomcat]# wget dlcdn.apache.org/tomcat/tomcat-8/v8.5.72/bin/apache-tomcat-8.5.72.tar.gz

[root@gzbsc001 mytomcat]# docker build -t mytomcat:8.5.72 . ##创建镜像
Successfully built 25102a5b9a73
Successfully tagged mytomcat:8.5.72

[root@gzbsc001 mytomcat]# docker images
REPOSITORY            TAG        IMAGE ID       CREATED             SIZE
mytomcat              8.5.72     25102a5b9a73   38 seconds ago      956MB

[root@gzbsc001 mytomcat]# docker run -P -it mytomcat:8.5.72 /bin/bash 

[root@gzbsc001 mynginx]# docker ps 
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                                         NAMES
7ec02971fd62   mytomcat:8.5.72   "/usr/local/tomcat8/…"   18 seconds ago   Up 17 seconds   0.0.0.0:49159->8080/tcp, :::49159->8080/tcp   reverent_franklin

image-20211117190932362

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注