文章目录

  • DokcerFile:按照层来构建image
  • 1、什么是 DockerFile
  • 2、使用DockerFile挂载数据卷
  • (1)创建dockerfile文件
  • (2)使用docker build构建镜像
  • (3)启动镜像并操作镜像
  • (4)验证挂载
  • (5)最后总结
  • 3. DockerFile编写细节
  • (1)查看ubuntu在docker hub中的官方dockerfile
  • (2) DockerFile的构建过程
  • (3) DockerFile常用指令
  • (4) CMD和ENTRYPOINT的区别


DokcerFile:按照层来构建image




add dockerfile s3 文件 dockerfile cd_linux


1、什么是 DockerFile

  • Dockerfile就是用来构建Docker镜像的构建文件,是一个命令脚本
  • 通过这个脚本可以生成镜像,镜像是一层一层的,而脚本也是一个个的命令,每个命令都是一层。

2、使用DockerFile挂载数据卷

(1)创建dockerfile文件

找一个测试文件夹,新建一个文件,取名例如dockerfile 然后在dockerfile中写入我们的命令脚本

FROM centos # 添加基础镜像
VOLUME ["volume01", "volume02"] # 添加两个容器数据卷,属于匿名挂载
CMD echo "--finished----success--" # 容器构建完成输出的信息
CMD /bin/bash # 指定终端命令

注意:

  • 创建一个Dockerfile文件,名字可以随机起,建议使用Dockerfile命名。
  • 文件中的指令都大写。
  • Dockerfile里面的每个命令,就是镜像的一层!
  • docker file中使用VOLUME给镜像添加一个或多个数据卷,但是其需要主机有这个目录,移植性不好

提示:

出于可移植和分享的考虑,用-v主机目录:容器目录这种方法不能够直接在Dockerfile中实现。

是由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有的宿主机上都存在这样的特定目录

(2)使用docker build构建镜像

docker build 参数:

test@P340:/$ sudo docker build --help

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
  -c, --cpu-shares int          CPU shares (relative weight)
  -f, --file string             Name of the Dockerfile (Default is 'PATH/Dockerfile')
  -m, --memory bytes            Memory limit
  -q, --quiet                   Suppress the build output and print image ID on success
  -t, --tag list                Name and optionally a tag in the 'name:tag' format
# -f 指定dockerfile文件路径;-t 指定镜像的`命名空间/镜像:TAG`
test@P340:/$ sudo docker build -f dockerfile -t test/ubuntu .
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM ubuntu
 ---> 1318b700e415
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in 1911ef59f958
Removing intermediate container 1911ef59f958
 ---> 656521e484a9
Step 3/4 : CMD echo "---end---"
 ---> Running in 2cb2a7e0d28a
Removing intermediate container 2cb2a7e0d28a
 ---> 1c060daa940e
Step 4/4 : CMD /bin/bash
 ---> Running in 4e8a5ccb6ccd
Removing intermediate container 4e8a5ccb6ccd
 ---> 4b88b2784076
Successfully built 4b88b2784076
Successfully tagged liufeng/ubuntu:latest

# 查看新构建好的镜像
test@P340:/$ sudo docker images
REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
test/ubuntu   latest    4b88b2784076   56 seconds ago   72.8MB
ubuntu           latest    1318b700e415   3 weeks ago      72.8MB

(3)启动镜像并操作镜像

test@P340:/$ sudo docker images
REPOSITORY       TAG       IMAGE ID       CREATED         SIZE
test/ubuntu   latest    4b88b2784076   8 minutes ago   72.8MB
ubuntu           latest    1318b700e415   3 weeks ago     72.8MB

test@P340:/$ sudo docker run -it --name ubuntu01 4b88b2784076 /bin/bash
root@7b0c1a867911:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume01  volume02

注意,进入容器之中就可以直接看到我们在images中挂载的volume1 和volume2连个容器卷了。

其实这两个文件夹就是我们在Dockerfile文件中定义的数据卷挂载,是以匿名挂载的方式挂载数据卷的。

在容器启动的时候,会自动挂载这两个数据卷目录。

(4)验证挂载

在我们打开的容器中的volume01或volume02文件夹中新建一个文件,写入点东西测试一下。然后退出容器。

查看一下我们容器数据卷的信息,因为是匿名挂载所以数据卷的名字是一大段字符

# 查看我们的容器
test@P340:/$ sudo docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                     PORTS     NAMES
7b0c1a867911   4b88b2784076   "/bin/bash"   7 minutes ago   Exited (0) 2 minutes ago             ubuntu01

# 查看容器元信息
test@P340:/data/liufeng/project/docker/test_volumn$ sudo docker inspect 7b0c1a867911
"Mounts": [
            {
                "Type": "volume",
                "Name": "89bb825b92fb7e9293dbeb1ed0c5f9647006e7f5fd571dec4f97b05f471adf64",
                "Source": "/var/lib/docker/volumes/89bb825b92fb7e9293dbeb1ed0c5f9647006e7f5fd571dec4f97b05f471adf64/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "42655cb1ce4f2b071858fe67ac50e8d74fc7ff409c2bfa9fb6e467c07de97ba7",
                "Source": "/var/lib/docker/volumes/42655cb1ce4f2b071858fe67ac50e8d74fc7ff409c2bfa9fb6e467c07de97ba7/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

根据查看到的容器名和地址进入看看

test@P340:/# cd /var/lib/docker/volumes/89bb825b92fb7e9293dbeb1ed0c5f9647006e7f5fd571dec4f97b05f471adf64/_data
test@P340:/var/lib/docker/volumes/89bb825b92fb7e9293dbeb1ed0c5f9647006e7f5fd571dec4f97b05f471adf64/_data# ls
hello_dockerfile

ok!!!可以看到我们在容器中创建的那一个用来测试挂载的dockerfile了

(5)最后总结

  1. dockerfile 名字可以任意,但是建议使用Dockerfile
  2. 使用dockerfile来创建挂载的时候注意如果使用绝对路径本机地址::容器地址,那么构建的镜像可能移植性受限,因为其要求主机上要有这个目录
  3. 如果使用匿名挂载的方式来构建dockerfile的挂载,那么可以使用docker inspect 容器id来查看容器的元数据,包括匿名挂载的位置

3. DockerFile编写细节

(1)查看ubuntu在docker hub中的官方dockerfile

ubuntu在dockerhub中的地址 :https://hub.docker.com/_/ubuntu 然后可以点击其中的一个版本,跳转到ubuntu的github地址中:
https://github.com/tianon/docker-brew-ubuntu-core/blob/a967c2b8734c77f7f89449d0b87c2e1eebf8b26e/bionic/Dockerfile 可以打开其dockerfile进行查看了:

FROM scratch
ADD ubuntu-bionic-oci-amd64-root.tar.gz /
CMD ["bash"]

(2) DockerFile的构建过程

Dockerfile构建步骤

  1. 编写一个 Dockerfile文件
  2. 使用 docker build 将其构建成为一个镜像
  3. 使用 docker run 运行镜像
  4. 使用 docker push 发布镜像


add dockerfile s3 文件 dockerfile cd_linux


(3) DockerFile常用指令

基础知识

  1. 每个保留关键字( 指令 )都必须是大写字母
  2. 每一个指令都会创建提交一个新的镜像层
  3. 指令的执行顺序从上到下
  4. # 表示注释(注意需要单独一行)

在 Docker 中创建镜像最常用的方式就是使用 Dockerfile. 其是一个 Docker 镜像的描述文件,包含了一条条的指令 : 每一条指令构建一层,因此每一条指令的内容就是描述该层应当如何构建. Dockerfile 常用指令如下图所示



add dockerfile s3 文件 dockerfile cd_docker_03


  • FROM : 基础镜像,一切从这里开始构建
  • MAINTAINER : 镜像的作者信息 : 姓名 + 邮箱
  • RUN : 镜像构建的时需要运行的命令
  • ADD : 将所需文件拷贝到镜像中,例如 nginx,redis等.
  • WORKDIR : 指定镜像的工作目录
  • VOLUME : 设置挂载目录
  • EXPOSE : 暴露端口配置
  • CMD : 指定容器启动时要运行的命令,但只有最后一个生效且可被替代
  • ENTRYPOINT : 与 CMD 功能相同,区别为其可追加命令
  • ONBUILD : 当构建一个被继承 Dockerfile 时这个指令就会被触发执行
  • COPY : 与 ADD 指令类似,即可将文件拷贝到镜像中
    ENV : 设置构建时所需的环境变量
  • USER : 指定运行用户

(4) CMD和ENTRYPOINT的区别

CMD:
CMD是一个容器的默认可执行体:也就是说,容器启动之后,默认执行的命令。

  • 如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么,就会使用cmd指定的默认的执行命令执行。同时也从侧面说明了entrypoint的含义,它才是真正的容器启动以后要执行命令。
  • 只有最后一个CMD才会被执行

CMD的官方说明:有三种用法

The CMD instruction has three forms:
 
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)

ENTRYPOINT
官方说明
An ENTRYPOINT allows you to configure a container that will run as an executable.

也就是说:ENTRYPOINT才是通常用于定义容器启动后执行命令的执行体

ENTRYPOINT有两种用法:

ENTRYPOINT has two forms:
 
ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
ENTRYPOINT command param1 param2 (shell form)

如果run后面有东西,那么后面的全部内容都会作为ENTRYPOINT的参数

比如如果dockerfile为:

FROM ubuntu
ENTRYPOINT ['ls','a']

那么使用run运行不加参数的时候,其显示的结果和CMD是一模一样的

docker run 容器ID

但是如果你在后面加上一个参数-l, 如果在CMD ['ls','a']之中会接收到错误,二在我们的ENTRYPOINT之中就是正确的。也就是ENTRYPOINT会将传入的内容都当作是参数,如果没有传入的参数,而CMD中有,他也会把CMD的参数当作是自己的参数执行。

CMD是覆盖,ENTRYPOINT是追加