Docker可以通过读取Dockerfile。Dockerfile是一个文本文档,它包含用户可以在命令行上调用的所有命令来组装镜像。使用docker build
用户可以创建一个连续执行几个命令行指令的自动化构建
首先写一个Dockerfile
FROM nginx # 基于一个基础镜像 RUN ls
运行 docker build . 构建一个镜像
.
当前上下文环境 这里使用当前目录(.)作为构建背景 .
可以放在-t -f 等指令之前 也可以放在指令后面
Sending build context to Docker daemon 6.144kB Step 1/1 : FROM nginx ---> f2f70adc5d89 Successfully built f2f70adc5d89 Successfully tagged my_nginx:2.0
[root@iZuf620p8rsr3faul3zsx6Z test1]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE my_nginx 2.0 41637892bcfc 19 seconds ago 142MB nginx latest f2f70adc5d89 8 days ago 142MB
有效的Dockerfile必须以FROM指令开始
语法: FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
参考文档:https://docs.docker.com/engine/reference/builder/#from
语法1: RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows) 语法2: RUN ["executable", "param1", "param2"] (exec form)
参考文档:https://docs.docker.com/engine/reference/builder/#run
这个WORKDIR指令可以为RUN, CMD, ENTRYPOINT, COPY和ADD中的指令指定工作文件夹。
语法: WORKDIR /path/to/workdir
参考文档:https://docs.docker.com/engine/reference/builder/#workdir
为镜像设置环境变量
语法: ENV <key>=<value> ...
参考文档:https://docs.docker.com/engine/reference/builder/#env
eg:
Dockerfile
FROM nginx RUN pwd WORKDIR /etc ENV mykey=myvalue
docker build
创建镜像,然后依次执行指令
[root@iZuf620p8rsr3faul3zsx6Z test1]# docker build . -t nginx_run_env_workdir Sending build context to Docker daemon 7.168kB Step 1/4 : FROM nginx ---> f2f70adc5d89 Step 2/4 : RUN pwd ---> Running in fca96ac4ffc3 / Removing intermediate container fca96ac4ffc3 ---> d254ae1be464 Step 3/4 : WORKDIR /etc **这里指定etc为工作目录** ---> Running in 96c839d4d559 Removing intermediate container 96c839d4d559 ---> 850465095d7d Step 4/4 : ENV mykey=myvalue **这里设置新的环境变量** ---> Running in 2d83734c81d1 Removing intermediate container 2d83734c81d1 ---> f77f64a01b10 Successfully built f77f64a01b10 Successfully tagged nginx_run_env_workdir:latest **构建成功 运行容器** [root@iZuf620p8rsr3faul3zsx6Z test1]# docker run -d --rm nginx_run_env_workdir a4569433802ec0853b5f3536ce66f0d55486e46e2ecb85b1f533305028aedef3 [root@iZuf620p8rsr3faul3zsx6Z test1]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a4569433802e nginx_run_env_workdir "/docker-entrypoint.…" 42 seconds ago Up 41 seconds 80/tcp dreamy_sanderson [root@iZuf620p8rsr3faul3zsx6Z test1]# docker exec -it a4569433802e bash **进入容器** root@a4569433802e:/etc# env **这里进入容器 默认进入etc文件夹** HOSTNAME=a4569433802e PWD=/etc PKG_RELEASE=1~bullseye HOME=/root NJS_VERSION=0.7.2 TERM=xterm SHLVL=1 mykey=myvalue **这里可以看到新加的环境变量** PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin NGINX_VERSION=1.21.6 _=/usr/bin/env root@a4569433802e:/etc#
这个COPY指令将新文件或目录从
语法1: COPY [--chown=<user>:<group>] <src>... <dest> 语法2: COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
参考文档:https://docs.docker.com/engine/reference/builder/#copy
ADD指令复制新文件、目录或远程文件url。
语法1: ADD [--chown=<user>:<group>] <src>... <dest> 语法2: ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
参考文档:https://docs.docker.com/engine/reference/builder/#add
eg:
Dockerfile
FROM nginx RUN pwd WORKDIR /etc ENV mykey=myvalue COPY ./a.txt /root/ ADD ./a.txt /root/c.txt ADD https://nginx.org/download/nginx-1.21.6.tar.gz /root
docker build . -t nginx_copy_add
构建镜像
docker run -d --rm nginx_copy_add
运行容器
[root@iZuf620p8rsr3faul3zsx6Z test1]# docker exec -it 548e96d26901 bash **进入容器** root@548e96d26901:/etc# cd /root root@548e96d26901:~# ls nginx-1.21.6.tar.gz a.txt c.txt **由COPY指令复制的a.txt 文件 和由ADD指令复制 c.txt 以及网络下载的nginx-1.21.6.tar.gz 文件** root@548e96d26901:~# cat a.txt **里面的内容也是完全一样的** aaaaawqewqewq root@548e96d26901:~# cat c.txt bbbbbbbb root@548e96d26901:~#
这个EXPOSE指令通知Docker容器在运行时侦听指定的网络端口。可以指定端口是否侦听TCP或UDP,如果未指定协议,则默认为TCP。
一般不使用EXPOSE指令指定的网络端口,在运行容器时使用 docker run
-p
或 -P
指令
语法: EXPOSE <port> [<port>/<protocol>...]
参考文档:https://docs.docker.com/engine/reference/builder/#expose
这个VOLUME指令创建一个具有指定名称的挂载点,并将其标记为保存来自本机主机或其他容器的外部挂载卷。值可以是JSON数组,VOLUME ["/var/log/"],或者具有多个参数的普通字符串,如VOLUME /var/log或VOLUME /var/log /var/db
和 docker run
-v
指令作用相当
语法: VOLUME ["/data"]
参考文档:https://docs.docker.com/engine/reference/builder/#volume
eg:
Dockerfile
FROM nginx WORKDIR /root EXPOSE 8080/tcp EXPOSE 8081/udp VOLUME /volume1
docker volume --help
查看数据卷挂载情况
Usage: docker volume COMMAND Manage volumes Commands: create Create a volume inspect Display detailed information on one or more volumes ls List volumes prune Remove all unused local volumes rm Remove one or more volumes
docker build . -t nginx_volume
docker run -d --rm --name nginx_volume nginx_volume
构建镜像并运行容器
**docker volume 可以查看到本地多了一条数据卷挂载信息** [root@iZuf620p8rsr3faul3zsx6Z test1]# docker volume ls DRIVER VOLUME NAME local 739de9625ef852803660a1d5b63c8457ebd90bd50cbbe815650846c3610adb71
docker inspect --help
查看容器信息
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...] Return low-level information on Docker objects Options: -f, --format string Format the output using the given Go template -s, --size Display total file sizes if the type is container --type string Return JSON for specified type
docker inspect nginx_volume
找到Mounts节点 Source 为宿主机对应容器挂载地址
"Mounts": [ { "Type": "volume", "Name": "739de9625ef852803660a1d5b63c8457ebd90bd50cbbe815650846c3610adb71", "Source": "/var/lib/docker/volumes/739de9625ef852803660a1d5b63c8457ebd90bd50cbbe815650846c3610adb71/_data", "Destination": "/volume1", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ],
[root@iZuf620p8rsr3faul3zsx6Z test1]# docker exec -it nginx_volume bash root@a1876b7b5872:~# cd / root@a1876b7b5872:/# ls bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var boot docker-entrypoint.d etc lib media opt root sbin sys usr volume1 root@a1876b7b5872:/# cd volume1/ **进入容器根目录volume1文件夹下** root@a1876b7b5872:/volume1# touch aaa.txt root@a1876b7b5872:/volume1# echo 123 > aaa.txt root@a1876b7b5872:/volume1# cat aaa.txt **创建一个文件** 123 root@a1876b7b5872:/volume1# exit **退出容器** exit [root@iZuf620p8rsr3faul3zsx6Z test1]# cd /var/lib/docker/volumes/739de9625ef852803660a1d5b63c8457ebd90bd50cbbe815650846c3610adb71/_data [root@iZuf620p8rsr3faul3zsx6Z _data]# ls **在宿主机相应位置上可以看到相同的文件** aaa.txt [root@iZuf620p8rsr3faul3zsx6Z _data]# cat aaa.txt 123 [root@iZuf620p8rsr3faul3zsx6Z _data]# touch bbb.txt [root@iZuf620p8rsr3faul3zsx6Z _data]# vim bbb.txt **在宿主机上创建一个新的文件** [root@iZuf620p8rsr3faul3zsx6Z _data]# docker exec -it nginx_volume bash root@a1876b7b5872:~# cd / root@a1876b7b5872:/# ls bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var boot docker-entrypoint.d etc lib media opt root sbin sys usr volume1 root@a1876b7b5872:/# cd volume1 root@a1876b7b5872:/volume1# ls **再次进入容器volume1文件夹, 发现了宿主机新创建的文件,数据卷挂载成功** aaa.txt bbb.txt
Dockerfile只能有一个CMD中的指令。如果你列出了多个CMD那么只有最后一个CMD会生效。
如果在运行docker run
时带上其他指令 CMD也不会生效
CMD主要目的为正在执行的容器提供默认值
语法1: CMD ["executable","param1","param2"] (exec form, this is the preferred form) 语法2: CMD ["param1","param2"] (as default parameters to ENTRYPOINT) 语法3: CMD command param1 param2 (shell form)
参考文档:https://docs.docker.com/engine/reference/builder/#cmd
和CMD指令类似,和CMD不同的是在运行docker run
时带上其他指令 ENTRYPOINT也会生效
使用docker run --entrypoint
可以重写ENTRYPOINT指令
语法1: ENTRYPOINT ["executable", "param1", "param2"] 语法2: ENTRYPOINT command param1 param2
参考文档:https://docs.docker.com/engine/reference/builder/#entrypoint
eg:
FROM nginx RUN pwd **RUN指令在构建时执行** CMD pwd CMD ls **CMD、ENTRYPOINT 指令在容器运行时执行** ENTRYPOINT echo 12345 ENTRYPOINT ["ls"] **ENTRYPOINT指令不会被覆盖 RUN指令可以被覆盖** CMD ["/root"] **两者结合可以做到在运行时输入不同参数,达到不同的效果**
docker build . -t nginx_ec
如下在运行时,输入不同的参数实现不同的操作
[root@iZuf620p8rsr3faul3zsx6Z /]# docker run --rm nginx_ec /var backups cache lib local lock log mail opt run spool tmp [root@iZuf620p8rsr3faul3zsx6Z /]# docker run --rm nginx_ec /dev core fd full mqueue null ptmx pts random shm stderr stdin stdout tty urandom zero [root@iZuf620p8rsr3faul3zsx6Z /]#
本文参考文档