Docker入门篇之搞懂Dockerfile

在前面的文章 图解Docker的整体架构 中,我们知道镜像是Docker的三大组件之一,本文我们将学习一下镜像的构建过程。主要围绕Dockerfile,已经常用的指令!

1. 镜像常用命令

下面罗列一下常用的与镜像有关的命令:

  1. 列举本地的镜像:docker images
  2. 拉取镜像:docker pull tomcat
  3. 在仓库中查找镜像:docker search tomcat
  4. 根据名称删除镜像:docker rmi tomcat:alpine
  5. 根据id删除镜像:docker rmi 8b8b1eb786b5
  6. 构建镜像:docker build -t mytest:v1 .
  7. 设置标签:docker tag tomcat:alpine tomcat:alpine-test
    相当于只是设置了软链接!下面可以看到Image ID都是一样的!
$ docker images
REPOSITORY    TAG           IMAGE ID       CREATED       SIZE
tomcat        alpine        8b8b1eb786b5   2 years ago   106MB
tomcat        alpine-test   8b8b1eb786b5   2 years ago   106MB

2. Dockerfile简介

如果说Docker容器是刚出炉的鱼香肉丝,Docker镜像就是鱼香肉丝这个菜品,那么Dockerfile就是鱼香肉丝这个菜品的菜谱!

菜谱中的每道工序决定了最后炒出来的鱼香肉丝菜的味道。
Dockerfile中的内容,最终也决定了最终运行起来的Docker容器!

前面的文章 Docker入门篇之Apache展示网页 制作了一个Apache的镜像,我们来看看镜像的内容:
在这里插入图片描述Dockerfile就是一个文本文件,里面包含一条条的指令!(类比成菜谱里面的做菜的每一个步骤)。

构建镜像时,默认会找上下文路径下的Dockerfile文件,所以如果在上下文的目录下的其他文件名,就需要用-f指定Dockerfile的位置和名称!

上下文路径

很中亚的docker命令是docker build。我们重点来剖析它!

docker build -t my-test .

-t:设置镜像名称和标签,默认标签是latest,完整格式my-test:latest
.:构建上下文路径

在前面的文章分析过,docker是C/S架构,docker build命令是在客户端执行的,但是真正构建镜像,是在服务器端进行的。

这样就会引出一个问题,我们的本地的一些文件想最终想包含在镜像中,就需要把它们发送到真正构建镜像的服务端!

处理过程:

  1. 这个上下文路径,存储的就是我们需要在镜像中包含的文件路径。
  2. 指定了它,docker build请求服务端时就会把它打包
  3. 真正构建镜像时,我们可以通过COPY指令,把它们复制到镜像中去。

3. Dockerfile指令

上面的Dockerfile涉及几种指令:FROM、RUN、COPY、CMD、EXPOSE,除此之外,还有其他指令,下面我们逐条分析它们!

3.1 FROM:指定基础镜像

指定要基础镜像,类似Java里面的类继承!
Docker Hub仓库里面有各种已经制作好的镜像,我们也可以基于它们制作新的镜像,也可以根据它们创建容器!

如果想马上有一套部署tomcat的环境,直接使用tomcat镜像创建容器!
如果想马上有一套CentOS环境,直接使用CentOS镜像创建容器!

FROM指令是必选的,否则会报错:
failed to solve with frontend dockerfile.v0: failed to create LLB definition: no build stage in current context
FROM中指定的镜像,就是后面指令的构建舞台(build stage)

3.2 COPY:复制文件

COPY指令和我们Linux中的cp命令类似!
最终目的是,从上下文路径中copy文件到容器的指定路径

3.3 RUN:运行命令(构建镜像时)

RUN指令的作用是制作镜像时执行一条命令!支持两种格式:
shell格式:

RUN touch test-1.txt

exec格式:

RUN ["touch", "test-2.txt"]

这样容器运行后,我们可以看到新建的两个文件:
在这里插入图片描述

3.4 CMD:运行命令(启动容器时)

CMD和前面的RUN都是运行命令。

区别是运行时机不一样:

  • RUN:构建镜像docker build)时运行命令
  • CMD:启动容器docker run)时运行命令

指定容器启动时的命令:

FROM alpine
RUN touch test-1.txt
RUN ["touch", "test-2.txt"]
CMD ["echo", "Hello Docker!"]

非常重要的一点:
CMD的作用是给容器指定默认的程序,所以当命令结束时,容器也会退出!

docker run my-test
Hello Docker!

也就是说容器的生命周期随着CMD指令的完成而退出!!!!

当Dockerfile中声明多条CMD指令时,前面的会被最后一条CMD命令覆盖!

FROM alpine
RUN touch test-1.txt
RUN ["touch", "test-2.txt"]
CMD ["echo", "Hello 1"]
CMD ["echo", "Hello 2"]

上面的容器,只会输出Hello 2

另外,CMD指令也会被docker run指定的命令覆盖!

docker run my-test echo "This is Docker"
This is Docker

3.5 ENTRYPOINT:运行命令(启动容器时)

作用类似CMD,同样多条ENTRYPOINT只会保留最后一条。
但是和CMD不同的是,它不会不会被docker run中的命令覆盖!

FROM alpine
RUN touch test-1.txt
RUN ["touch", "test-2.txt"]
CMD ["echo", "Hello 1"]
CMD ["echo", "Hello 2"]
ENTRYPOINT ["echo", "Hello ENTRYPOINT 1"]
ENTRYPOINT ["echo", "Hello ENTRYPOINT 2"]

3.6 ARG:设置变量

相当于局部变量,只是在构建镜像时可用$VERSION_ARG

ARG VERSION_ARG=1001

3.7 ENV:设置环境变量

ARG的加强版,同时设置到环境变量中:

ENV VERSION_ENV=8
ARG VERSION_ARG=1001

在这里插入图片描述

3.8 VOLUME:定义默认的数据卷

定义匿名的数据卷,如果docker run是没有挂载数据卷,会用这里默认的数据卷!如果docker run指定-v已设置的为主!

主要是防止docker run时没有挂载数据卷,容器删除后,容器内的数据会丢失!
测试一下
定义数据卷

FROM alpine
RUN touch nobody.txt
VOLUME test_volume

启动时并不挂载数据卷:

 docker run -dit my-test /bin/sh

查看数据卷:

$ docker volume ls
DRIVER    VOLUME NAME
local     583336a1717deb1e674fe29934b1b0a9ae7a69d9a8f07c8168d9462c74ca4928

即使容器被删除后,数据卷还在!

3.9 EXPOSE :声明端口

仅仅是声明默认的端口!

比如Apache中声明了80端口:

FROM php:7.0-apache
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
COPY ./html/test.html /var/www/html/
EXPOSE 80

有两个作用:

  1. 相当于注释,告诉修改镜像的人,这些容器端口对外暴露了
  2. 作为默认端口使用
FROM php:7.0-apache
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
COPY ./html/test.html /var/www/html/
EXPOSE 80

启动容器是,自动映射端口:

docker run -d -P apache_test:1.0

可以看到本机的随机端口49153会映射到容器的80端口!这样我们可以访问:http://localhost:49153/test.html

$ docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED          STATUS          PORTS                   NAMES
75f0731ec926   apache_test:1.0   "docker-php"   28 seconds ago   Up 27 seconds   0.0.0.0:49153->80/tcp   dreamy_rhodes

3.10 WORKDIR:设置工作目录

构建镜像的过程中,每个RUN都会新建一层,所以只有工作目录会一直存在!相当于构建镜像时,层与层之间的共享目录

3.11 USER:指定命令执行的用户

切换用户,然后执行接下来的指令

USER root
RUN touch root.txt
USER nobody
RUN touch nobody.txt
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值