docker 入门1
Author:chenj_x12@foxmail.com
安装
docker的安装教程可以看菜鸟的:Docker 教程 | 菜鸟教程 (runoob.com)
测试是否安装成功
# 运行:docker run hello-world,出现如下文字说明安装成功
Hello from Docker !
This message shous that your installation appears to be uorking correctly.To generate this message,Docker took the follouing steps:1. The Docker client contacted the Docker daemon.,
2. The Docker daemon pulled the "hello-uorld" image from the Docker Hub.( amd64)
3. The Docker daemon created a new container from that image uhich runs theexecutable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client,uhich sent it
to your terminal.
配置镜像加速
安装好docker后,需要给它配置镜像加速,毕竟直接访问太慢了
步骤如下:
cd /etc/docker
touch daemon.json
vim daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1panel.live",
"https://registry.docker-cn.com",
"https://mirrors.docker.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
# 还有多的镜像站可以接着放,只要这里面有一个能用就行
]
}
如果有一定能力的话可以去阿里云、华为云找容器镜像加速服务,具体步骤网上找
docker客户端
基于终端命令行的docker客户端非常简单,可以直接输入 docker命令查看指令:

一样的,可以使用 docker COMMAND –help,查看对应指令的详细用法
容器使用
启动容器
docker run
使用 docker run (参数)images [COMMAND] 启动一个容器
eg:docker run -it ubuntu /bin/bash
root@chenjx12:~/dc# docker run -it ubuntu /bin/bash
root@e88f80e041c2:/#
发现了什么,root后面的东西变了对不对
这说明我们顺利的启动了容器,并且进入到了容器里面
现在就可以在容器里进行操作了
e88f80e041c2就是这个容器的ID,唯一的那种
如果我们选择后台运行 -d 参数,容器id会回显在终端
参数说明:
-i 使用交互式操作
-t 开启终端
-d/--detach 后台运行
--name <new_name> 容器命名
-rm 退出容器时自动删除
--restart=always 挂了就自动重启
-v/--volume 挂载卷
-e/--env 设置环境变量
# 容器连接相关(后面会讲)
-p 端口映射
-P 端口随机映射
/bin/bash 指明启动这个容器进入之后要执行什么命令
那docker run里的images是什么呢,它就是另一个重点,镜像
docker run -it ubuntu /bin/bash
docker会先在本地查找是否有ubuntu(:latest)的镜像
如果有,就基于它创建一个容器
如果没有,它就自动执行 docker pull ubuntu:latest 拉取一个镜像下来再创建容器
停止/运行的容器
首先需要查看容器的状态,使用命令如下
docker ps (参数)
=
无参数运行该命令会列出所有 “正在” 运行的容器,包括它们的容器 ID、镜像、命令、创建时间、状态、端口和名称
参数说明:
-a/--all 列出所有的容器(包括已经挂掉的)
-q/--quiet 只显示容器id
--format 自定义输出格式
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}"
这将按照指定的格式列出容器的 ID、名称和使用的镜像
-l/--latest 列出最近创建的容器
-n numb 后接数字列出最后创建的 numb 个容器
-f/--filter 过滤输出
一般直接使用 docker ps -a
停止容器:docker stop <容器id>
启动/重新启动容器:docker start/restart <容器id>
进入容器
在使用 -d 参数时,容器启动后会进入后台
此时想要进入容器,有两个指令可以实现:
docker attach <容器id>
使用该命令进入容器,再退出容器后容器会被停止
docker exec -it <容器id> /bin/bash
使用该命令退出后不会停止,推荐使用
注意:
想要再次进入容器的前提是容器还在运行,可以使用docker ps的status查看容器是否还在运行
docker作为一种节约资源的进程,会在当前容器没有任务执行的时候把它挂掉
也就是说,如果你的容器挂掉了,它里面就没有任务了,也就进不去了
同样的,正在后台运行的容器被docker stop停止了,也进不去,只是它不会被挂掉
退出容器
直接在容器的终端输入 exit就可以退出容器回到宿主机
容器导出/导出
docker export/import
docker export 命令用于将容器的文件系统导出为一个 tarball 文件。这不会包括容器的元数据或历史记录
docker export -o mycontainer.tar mycontainer
如果你不指定
-o选项,则导出的 tarball 将会输出到标准输出(stdout)这时就可以直接重定向
docker export mycontainer > mycontainer.tar
docker import 命令用于从 tarball 文件中创建一个新的 Docker 镜像。这个 tarball 文件通常是由 docker export 命令创建的
cat mycontainer.tar | docker import - mynewimage
如果有一个tarball文件:
docker import mycontainer.tar mynewimage
这将创建一个新的镜像
mynewimage,其内容来自mycontainer.tar文件。docker import 还可以指定一个url或者某个目录进行导入,如:
docker import http://example.com/example_contain.tgz example/imagerepo
注意:
docker export导出的 tarball 不包含容器的元数据,例如标签、环境变量等。它只包含容器文件系统的内容。docker import创建的新镜像会丢失所有历史记录和层信息,只有一个单独的层。
删除容器
docker rm
# 删除一个停止的容器
docker rm <容器id/名称>
# 强行删除一个正在运行的容器
docker rm -f <容器id/名称>
# 删除所有停止的容器(结合shell)
docker rm $(docker ps -aq)
# 删除所有容器
docker rm -f $(docker ps -aq)
镜像使用
获取镜像:
docker pull
使用 docker pull <image_name:tag> 从 “仓库” 中获取镜像
# tag为空的话默认为 latest
比如 docker pull ubuntu,默认拉取的镜像版本为 ubuntu:latest
root@chenjx12:~/dc# docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
eda6120e237e: Pull complete
Digest: sha256:b359f1067efa76f37863778f7b6d0e8d911e3ee8efa807ad01fbf5dc1ef9006b
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
这里就是从仓库中拉取到了官方的镜像 ubuntu:latest
# 批量拉取 docker pull -a/--all-tags ubuntu
批量拉取会拉取所有标签的ubuntu
# 怎么拉取别人的镜像
docker pull user/repo:tag
拉取用户名为user标签为tag的repo镜像
那么要怎么知道我们拉取的镜像仓库里有没有我们要的那个版本的镜像呢
docker search
使用 docker search images 可以在仓库中搜索名为images的镜像
常用的一些选项:
-f/--filter 添加条件搜索
--limit 限制搜索出的结果数量,默认为25条
--no-trunc 不截断输出,显示完整的镜像描述
eg:
docker search --limit 5 ubuntu 只显示前5个搜索结果
docker search -f "is-offical=true" ubuntu 只显示官方镜像
docker search --filter "is-automated=true" ubuntu 只显示自动化构建的镜像
docker search -f "stars=100" ubuntu 只显示拥有超过100星标的镜像
使用docker search得到搜寻结果之后就能够知道哪些镜像有,哪些没有
一般推荐下载星标最多的官方镜像,因为你也不知道别人上传的乱七八糟的镜像里有什么东西
列出镜像
可以在终端输入 docker images 来列出本地的镜像
root@chenjx12:~/dc# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 61b2756d6fa9 2 weeks ago 78.1MB
nginx latest 9527c0f683c3 6 weeks ago 188MB
ubuntu 20.04 9df6d6105df2 7 weeks ago 72.8MB
hello-world latest d2c94e258dcb 17 months ago 13.3kB
ubuntu 15.10 9b9cb95443b5 8 years ago 137MB
# 各项属性说明
REPOSITORY:表示镜像的仓库源
TAG:镜像的标签
IMAGE ID:镜像ID
CREATED:镜像创建时间
SIZE:镜像大小
用镜像跑个容器
镜像导入/导出
docker save/load
docker save 命令用于将一个或多个镜像保存为一个 tarball 文件。与 docker export 不同的是,docker save 保存的是镜像而不是容器,并且会保存镜像的所有历史记录和层信息
docker save -o myimage.tar myimage 保存单个镜像
docker save -o myimages.tar myimage1 myimage2 将
myimage或myimage1和myimage2镜像保存到myimage.tar文件中
docker load 命令用于从 tarball 文件中加载一个或多个镜像。与 docker import 不同的是,docker load 会恢复镜像的所有历史记录和层信息
docker load < myimage.tar
docker load -i myimage.tar
注意:
docker save和docker load保存和加载的是镜像,包括所有层和历史信息。docker export和docker import保存和加载的是容器快照,不包括历史信息,只有一个压缩的文件系统。
因此,如果你需要保存一个镜像及其所有层,以便在其他 Docker 主机上使用,你应该使用 docker save 和 docker load。如果你只是需要从一个容器创建一个新的镜像,而不需要保存层信息,那么可以使用 docker export 和 docker import
删除镜像
docker rmi
即 docker rm (image)
docker rmi [image_id]
docker rmi [image_name]:[tag]
# 强行删除,比如有容器正在使用该镜像
docker rmi -f [image_id]
# 删除所有未标记的镜像,有时候,你会有一些未标记或未使用的镜像,可以使用以下命令清理:
docker image prune
# 删除所有
docker rmi -f $(docker images -q)
容器连接
容器–网络
先前在**容器使用–启动容器** 中就讲了,docker run 后跟 -p和-P参数可以做到端口映射 和 端口随机映射
首先说明为什么要做端口映射:
容器构建了一个隔离于宿主机的环境,而外部网络只能访问到宿主机
要在宿主机外的网络仍能够访问到容器,就必须把容器内运行服务的端口映射到宿主机上
即,访问宿主机的这些端口等同于访问相应容器的端口
也就是为了容器能够被宿主机外的网络访问到,所以做了端口映射
比如运行nginx,mysql之类的服务的容器
接下来看看具体的指令该怎么用,就拿一个nginx容器做例子吧
# 端口映射
docker run -d -p 8080:80 --name test_p1 nginx
这个指令就是将容器的 80 端口映射给了宿主机的 8080 端口
这样访问宿主机的 8080 端口就可以访问到nginx服务
# 端口随机映射
docker run -d -P --name test_p2 nginx
Docker会自动选择宿主机的一个空闲端口(默认是32768到61000)来进行映射
该指令不需要指定端口,它会根据容器中暴露的端口对宿主机进行随机映射
那么问题来了,我怎么知道哪些端口可用哪些不能呢
# 可以查看存活的容器
docker ps
使用该指令查看存活容器的 PORT项,那些是它正在占用的端口
当然,你也可以给它加上个 -a 和 --format参数,列出所有容器
# 查看单个容器的端口映射
docker port [container_id/name]
回显与该容器相关的所有端口映射
# 查看容器详细信息
docker inspect [container_id/name]
在输出的JSON结果中,可以找到 NetworkSettings 部分,它包含了端口映射的详细信息
容器–容器
docker除了容器和镜像,还在本地提供了容器连接的桥梁
docker 桥接网络
当Docker安装完成后,它会自动创建一个名为 docker0 的Linux网桥。这个网桥允许容器与宿主机以及容器之间进行通信。Docker容器默认连接到这个桥接网络
通过它可以完成宿主机与容器间的通信
查看docker桥接网络
使用指令 ifconfig docker0 或者 brctl show
回显docker0网桥的详细信息,包括ip地址、子网掩码等
自定义docker桥接网络
# docker network create -d bridge test-bet
使用该指令创建一个名为 test-net 的桥接网络,类型是 bridge
参数 -d 指定docker网络类型,有bridge、overlay
# docker run -itd --name test1 --network test-net ubunut /bin/bash
# docker run -itd --name test2 --network test-net ubuntu /bin/bash
运行两个名为test1和test2的容器,并加入到名为test-net的docker网络中
# docker exec -it test1 /bin/bash
进入容器test1
# apt-get update
# apt install iputils-ping
更新下载ping
# ping test2
可以发现可以ping的通
这说明test1和test2在同一个容器网络中
配置DNS
自动配置
我们可以在宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS:
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}
设置后,启动容器的DNS会自动配置为114.114.114.114和8.8.8.8 配置完需要重启docker才能生效
systemctl restart docker
手动指定
如果只想在指定的容器设置DNS,可以使用如下指令:
docker run -it --rm -h host_ubuntu --dns=114.114.114.114 --dns-search=test.com ubuntu
参数说明:
--rm:容器退出时自动清理容器内部的文件系统
-h HOSTNAME 或者 --hostname=HOSTNAME: 设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts
--dns=IP_ADDRESS: 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名
--dns-search=DOMAIN: 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com
如果在容器启动时没有指定 –dns 和 –dns-search,Docker 会默认用宿主主机上的 /etc/resolv.conf 来配置容器的 DNS
Dockerfile
Dockerfile是啥
Dockerfile 是一个文本文件,其中包含了构建docker 镜像的所有指令
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明
通过定义一系列命令和参数,Dockerfile 指导 Docker 构建一个自定义的镜像
docker build
docker build 会根据Dockerfile中的指令,依次执行并构建镜像,指令如下:
docker build (参数) [image_name]:[tag] [Path]
参数说明:
-f 指定Dockerfile的位置(如果不在当前目录下)
-t 设置镜像名称和可选的标签
--build-arg 设置构建时变量
--no-cache 不使用构建缓存
[Path]:Dockerfile 的位置,一般为 . ,表示在当前目录下寻找
注意:路径下有且仅能有一个Dockerfile文件
注意:以前是只能Dockerfile,现在dockerfile也可以了
dockerfile指令
Dockerfile 指令 说明
FROM 指定基础镜像,用于后续的指令构建。
MAINTAINER 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 在构建过程中在镜像中执行命令。
CMD 指定容器创建时的默认命令。(可以被覆盖)
ENTRYPOINT 设置容器创建时的主要命令。(不可被覆盖)
EXPOSE 声明容器运行时监听的特定网络端口。
ENV 在容器内部设置环境变量。
ADD 将文件、目录或远程URL复制到镜像中。
COPY 将文件或目录复制到镜像中。
VOLUME 为容器创建挂载点或声明卷。
WORKDIR 设置后续指令的工作目录。
USER 指定后续指令的用户上下文。
ARG 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL 设置发送给容器以退出的系统调用信号。
HEALTHCHECK 定义周期性检查容器健康状态的命令。
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。
接下来,会稍微细致的讲一下常用的指令
FROM 指令:往往是Dockerfile 的第一条,指定base image
FROM ubuntu # 指定ubuntu:latest作为基础镜像
MAINTAINER chenjx12 # 指定该dockerfile的作者为chenjx12(更换为LABEL)LABEL maintainer=“chenjx12@foxmail.com” # 指定作者chenjx12 LABEL =
RUN echo ‘这是一个本地构建的镜像’ > /tmp/1.txt
用于执行后面跟着的命令行命令,RUN 有两种格式:
shell格式
RUN <终端命令行命令>
exec格式
RUN [“可执行文件”, “参数1”, “参数2”]
例如:
RUN ["./test.php", “dev”, “offline”] 等价于 RUN ./test.php dev offline
注意:Dockerfile每次执行都会在docker镜像上新建一层,过多无意义的层会造成镜像膨胀过大
多个RUN指令可以 && 符号连接命令,这样执行后,只会创建 1 层镜像
CMD /bin/bash == CMD [“/bin/bash”]
即运行镜像时默认执行/bin/bash,但是可以更改
比如:docker run -it ubuntu:latest cat /tmp/1.txt
这条指令运行容器时就会执行 cat /tmp/1.txt
ENTRYPOINT 同理,但是有细微的区别,后面会讲
EXPOSE 80
声明容器运行暴露听的特定的网络 80 端口,这样就可以访问在 80 端口运行的服务
仅仅只是声明端口
作用:
- 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射
- 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口
ENV NAME = “chenjx12”
指定环境变量NAME为chenjx12
ARG 同理,也有细微区别,后讲
ADD Path/file
将 Path路径下的file文件/目录复制到镜像中
也可以使用 url
COPY 同,细微区别,后讲
WORKDIR /opt
指定工作目录为 /opt
也就是进入容器后的目录为 /opt
指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在
USER root
指定工作用户为root
也就是进入容器后的身份为root
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)
只能用于切换用户,如果需要添加用户还需要再RUN 一条指令添加用户
VOLUME /data
挂载容器内的/data文件夹,在容器运行时,该目录自动挂载为匿名卷,任何向该目录写入数据的操作都不会被容器记录
保证容器存储层的无状态理念
定义匿名数据卷,在启动容器时忘记挂载数据卷,会自动挂载到匿名卷
作用:
- 避免重要的数据,因容器重启而丢失,这是非常致命的
- 避免容器不断变大
ONBUILD
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
格式:
ONBUILD <其它指令>
CMD & ENTRYPOINT
首先这俩都可以使用shell格式和exec格式,都没差
主要区别在于,一个是默认执行(可以更改);一个是主要执行(不允许更改)
并且它们在传参上也有所不同
比如现在,我想运行一个ubuntu容器,让它帮我用curl命令查看一下本机的ip
先看看直接拉取一个ubuntu下来,怎么执行
# docker pull ubuntu:20.04
# docker run -it <id> /bin/bash
# apt-get update
# apt-get install -y curl
# curl -s http://ipinfo.io/ip
root@c20b356e8ec0:/# curl -s http://ipinfo.io/ip
47.120.34.132
这里就会回显你的ip地址,如果我加上 -i 参数,则会输出HTTP响应头的详细信息
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# curl -s http://ipinfo.io/ip -i
HTTP/1.1 200 OK
date: Thu, 03 Oct 2024 09:59:20 GMT
content-type: text/plain; charset=utf-8
Content-Length: 13
access-control-allow-origin: *
via: 1.1 google
strict-transport-security: max-age=2592000; includeSubDomains
那么我们自行构建镜像呢
# 咱接着来看看 ENTRYPOINT 版的,dockerfile_1
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y curl
ENTRYPOINT ["curl", "-s", "http://ipinfo.io/ip"]
这样就行了,build一下运行容器试试
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# docker build -t curl_ip:test .
[+] Building 0.1s (6/6) FINISHED docker:default
=> [internal] load build definition from dockerfile 0.0s
=> => transferring dockerfile: 142B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/2] FROM docker.io/library/ubuntu:20.04 0.0s
=> CACHED [2/2] RUN apt update && apt install curl -y 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:050f1c97507ca5e73b95c5659b4c9f23e249289e71bdad2bf101b2593e6116ba 0.0s
=> => naming to docker.io/library/curl_ip:test 0.0s
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
flask_web latest 69ce5c1bb4e0 20 hours ago 866MB
curl_ip test 050f1c97507c 30 hours ago 143MB
test_blog latest 4deac4dd6f5b 41 hours ago 141MB
nginx latest 605c77e624dd 2 years ago 141MB
ubuntu 20.04 ba6acccedd29 2 years ago 72.8MB
hello-world latest feb5d9fea6a5 3 years ago 13.3kB
centos 7.8.2003 afb6fca791e0 4 years ago 203MB
# 那个curl_ip就是构建出来的了,接着使用容器运行它
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# docker run -it 050
47.120.34.132
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# docker run curl_ip:test -i
HTTP/1.1 200 OK
date: Thu, 03 Oct 2024 10:09:24 GMT
content-type: text/plain; charset=utf-8
Content-Length: 13
access-control-allow-origin: *
via: 1.1 google
strict-transport-security: max-age=2592000; includeSubDomains
47.120.34.132
# 可以发现两个都可以
那么CMD呢,把dockerfile改一下就好了
FROM ubuntu:20.04
RUN apt update && apt install curl -y
CMD ["curl", "-s", "http://ipinfo.io/ip"]
接着构建,运行
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# docker run -it f28
47.120.34.132
# 显然直接运行出一个容器是没问题的
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# docker run curl_ip:test -i
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-i": executable file not found in $PATH: unknown.
# 加上 -i 参数,发现报错了
[root@iZf8z1f6vdo3jdz69xilspZ curl_ip]# docker run curl_ip:test curl -s http://ipinfo.io/ip -i
HTTP/1.1 200 OK
date: Fri, 04 Oct 2024 00:27:08 GMT
content-type: text/plain; charset=utf-8
Content-Length: 13
access-control-allow-origin: *
via: 1.1 google
strict-transport-security: max-age=2592000; includeSubDomains
# 当你自己在后面把完整的命令输入之后才行
这就是为什么说,CMD 指令可以被覆盖,是默认执行的命令
当你运行时的 COMMAND 有了其他指令,docker 就会优先处理其他指令,而CMD 就被覆盖了
而 ENTRYPOINT 指令不可被覆盖,是主要执行的命令
这时就不需要在运行容器时加其他指令,但是可以加参数
下面是来自[菜鸟教程的原文](Docker Dockerfile | 菜鸟教程 (runoob.com))
CMD
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
- CMD 在docker run 时运行。
- RUN 是在 docker build。
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
格式:
CMD <shell 命令>
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。
ENTRYPOINT
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 –entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
格式:
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。
示例:
假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
1、不传参运行
docker run nginx:test
容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
2、传参运行
docker run nginx:test -c /etc/nginx/new.conf
容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
nginx -c /etc/nginx/new.conf
ADD & COPY
ADD
ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
COPY
复制指令,从上下文目录中复制文件或者目录到容器里指定路径。
格式:
COPY [--chown=<user>:<group>] <源路径1>... <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]
[–chown=:]:可选参数,用户改变复制到容器内文件的拥有者和属组。
<源路径>:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:
COPY hom* /mydir/
COPY hom?.txt /mydir/
ENV & ARG
ENV
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
ARG
构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 –build-arg <参数名>=<值> 来覆盖。
格式:
ARG <参数名>[=<默认值>]