Linux学习 day11之docker续集

使用 Docker 容器

创建容器

Docker 中,真正对外提供服务的还是容器,本小节咱们来创建一个容器。

创建容器的格式:docker run [option] image [cmd]
如:docker run -d --name nginx -p 80:80 nginx

容器启动参数

-d 以守护进程方式运行
-p 指定映射端口
-P 随机映射端口
-i 保持标准输入打开
-t 分配一个伪终端
-v 设置挂载文件到主机上
--rm 当容器关闭时自动删除
--name 为启动的容器设置一个名字
--network 指定使用哪个网络
-e 设置容器中的环境变量
--link 链接到另一个容器
-h 指定容器内的主机名

停止容器

docker终止容器是首先向容器发送 SIGTERM 信号,等待一段时间超时后(默认 10 秒),再发送 SIGKILL 信号来终止容器。

语法:docker stop nginx

NGINX 容器被我们终止后。这个时候我们也可以重新启动这个容器。
docker start nginx


进入容器

在使用容器的过程中,我们难免需要进入容器进行排查问题。下面我们就来介绍进入容器的集中方式。

attach

attach 是最早 docker 官方推出的进入容器的命令了,不过使用该命令有一个问题。当多个窗口同时使用该命令进入该容器时,所有的窗口都会同步显示。如果有一个窗口阻塞了,那么其他窗口也无法再进行操作,当所有窗口退出时,容器结束。

`docker attach nginx`

127.0.0.1 - "GET / HTTP/1.1" 308 171 "-" "curl/7.59.0" 0.000 - .

exec

attach 之后,exec 是官方推出的有一个新的进入容器的命令,这个命令相当于在容器中执行一个命令

docker exec -it nginx /bin/bash

nginx [ / ]$
nginx [ / ]$

nsenter

需要配合 docker inspect 来使用(早期没有 exec 命令时,企业当中最长用的方式之一),Docker 是用 golang语言开发,所以它也支持 go 语言的摸版语法。

nsenter --target $( docker inspect -f {{.State.Pid}}nginxv1 ) --mount --uts --ipc --net --pid

mesg: ttyname failed: No such device
root@6f99ae8757f7:/#

ssh

在生产环境中排除了使用 docker attach 命令进入容器之后,相信大家第一个想到的就是 ssh。在镜像(或容器)中安装 SSH Server,这样就能保证多人进入容器且相互之间不受干扰了,相信大家在当前的生产环境中(没有使用Docker 的情况)也是这样做的。但是使用了 Docker 容器之后不建议使用ssh 进入到Docker容器内。

总结

进入 docker container中一般情况下有 4 种方式,最常用的是execnsenter这两种。

Nsenterexec之间的区别?

  • Execdocker 自带的命令,NsenterLinux 提供的命令。
  • Exec相当于在容器内执行一个命令,而Nsenter 是仅仅进入容器之中而已。

删除容器

可以使用 docker rm 命令来删除处于终止或退出状态的容器,命令格式为:docker rm container
如: docker rm nginx

强制删除

强制删除一个正在运行的容器
docker rm -f nginx


导入与导出容器

某些时候,需要将容器从一个系统迁移到另外一个系统,此时可以使用 Docker 的导人和导出功能,这也是 Docker 自身提供的一个重要特性。

导出容器

导出容器是指,导出一个已经创建的容器到一个文件,不管此时这个容器是否处于运行状态 可以使用docker [container] export 命令,该命令格式为:
docker export daf9c3656be3 > nginx.tar

导入容器

导出的文件又可以使用 docker [ container] import 命令导人变成镜像,该命令格式为:
docker import nginx.tar test/nginx:v1

实际上,既可以使用docker load命令来导入镜像存储文件到本地镜像库,也可以使 docker [container] import命令来导入一个容器快照到本地镜像库 这两者的区别在于 容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积更大 此外,从容器快照文件导人时可以重新指定标签等元数据信息。

查看容器

查看容器详情可以使用docker container inspect [OPTIONS] CONTAINER [CONTAINER . .. ]子命令

[root@alvin-test-os ~]# docker inspect k8s
[
	{
	"Id": "726b695a337c63b2ba617ed282171dff82a3d51cc0bdc43194ce63beaf656c38",
	"Created": "2020-11-16T04:05:53.271281122Z",
	"Path": "docker-entrypoint.sh",
	"Args": 
		[
		"./start"
		],
	... 此处略去千百行
	}
]

容器命令详解

复制命令

复制命令类似于 Linux 系统中的scp命令,是将宿主主机上的内容上传到容器中,也可能是将容器中的文件下载到宿主主机中。

# 将容器中的内容复制到宿主主机
[root@alvin-test-os ~]# docker cp 726b695a337c:/opt/start .
[root@alvin-test-os ~]# ls | grep start
Start

#将宿主主机中的文件复制到容器中
[root@alvin-test-os ~]# docker cp start 726b695a337c:/root
[root@alvin-test-os ~]# docker exec 726b695a337c ls /root
start

Docker 网络

Docker 本身的技术依赖于 Linux 内核虚拟化技术的发展。所以Docker 对 Linux 内核的特性有很强的依赖。
本章主要介绍Docker所使用的 Linux 网络技术。

网络基础

其中 Docker 使用到的与 Linux 网络有关的技术分别有:网络名称空间、Veth、Iptables、网桥、路由。

网络名称空间

为了支持网络协议栈的多个实例,Linux 在网络协议栈中引入了网络名称空间(Network Namespace),这些独立的协议栈被隔离到不同的命名空间中。处于不同的命名空间的网络协议栈是完全隔离的,彼此之间无法进行网络通信,就好像两个“平行宇宙”。通过这种对网络资源的隔离,就能在一个宿主机上虚拟多个不同的网络环境,而 Docker 正是利用这种网络名称空间的特性,实现了不同容器之间的网络隔离。在 Linux 的网络命名空间内可以有自己独立的Iptables 来转发、NATIP 包过滤等功能。

Linux 的网络协议栈是十分复杂的,为了支持独立的协议栈,相关的这些全局变量都必须修改为协议栈私有。最好的办法就是让这些全局变量成为一个 Net Namespace 变量的成员,然后为了协议栈的函数调用加入一个Namespace参数。这就是 Linux 网络名称空间的核心。所以的网络设备都只能属于一个网络名称空间。当然,通常的物理网络设备只能关联到 root这个命名空间中。虚拟网络设备则可以被创建并关联到一个给定的命名空间中,而且可以在这些名称空间之间移动。
在这里插入图片描述

创建一个命名空间

[root@alvin-test-os ~]# ip netns add test01
[root@alvin-test-os ~]# ip netns add test02
[root@alvin-test-os ~]# ip netns list
test02
test01

Veth 设备

引入 Veth 设备对是为了在不同的网络名称空间之间进行通信,利用它可以直接将两个网络名称空间链接起来。由于要连接的两个网络命名空间,所以Veth 设备是成对出现的,很像一对以太网卡,并且中间有一根直连的网线。既然是一对网卡,那么我们将其中一端称为另一端的peer。在Veth 设备的一端发送数据时,它会将数据直接发送到另一端,并触发另一端的接收操作。
在这里插入图片描述

Veth 设备操作

创建Veth 设备对
ip link add veth type veth peer name veth001
  • 生成了两个 veth 设备, 互为对方的 peer
绑定命名空间

ip link set veth001 netns test01

  • ip link show | grep veth已经查看不到 veth001,当我们进入test01 命名空间之后,就可以查看到:
    ip netns exec test01 bash
Veth分配IP
# 退出名称空间先
exit

# 设置 IP
[root@alvin-test-os ~]# ip netns exec test01 ip addr add 172.16.0.111/20 dev veth001

# 启用 IP
[root@alvin-test-os ~]# ip netns exec test01 ip link set dev veth001 up

# 查看
[root@alvin-test-os ~]# ip netns exec test01 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
14: veth001@if15: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
LOWERLAYERDOWN group default qlen 1000
link/ether 96:f1:a2:1d:1d:10 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.16.0.111/20 scope global veth001
valid_lft forever preferred_lft forever
  • 这个时候双方就通了。
查看对端 Veth 设备

ip netns exec test01 ethtool -S veth001

为对端Veth设备设置IP
[root@alvin-test-os ~]# ip addr add 172.16.0.112/20 dev veth
[root@alvin-test-os ~]# ip link set dev veth down
[root@alvin-test-os ~]# ip link set dev veth up
[root@alvin-test-os ~]# ping 172.16.0.111
PING 172.16.0.111 (172.16.0.111) 56(84) bytes of data.
64 bytes from 172.16.0.111: icmp_seq=1 ttl=64 time=0.126 ms
64 bytes from 172.16.0.111: icmp_seq=2 ttl=64 time=0.081 ms
^C
--- 172.16.0.111 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.081/0.103/0.126/0.024 ms

网桥

Linux 可以支持多个不同的网络,它们之间能够相互通信,就需要一个网桥。 网桥是二层的虚拟网络设备,它是把若干个网络接口“连接”起来,从而报文能够互相转发。网桥能够解析收发的报文,读取目标 MAC 地址的信息,和自己记录的 MAC 表结合,来决定报文的转发目标网口。

网桥设备 brO 绑定了 eth0eth1 。对于网络协议械的上层来说,只看得到 brO 。因为桥接是在数据链路层实现的 ,上层不需要关心桥接的细节,于是协议枝上层需要发送的报文被送到 brO ,网桥设备的处理代码判断报文该被转发到 ethO 还是 ethl ,或者两者皆转发。反过来,从 ethO 或从 ethl 接收到的报文被提交给网桥的处理代码,在这里会判断报文应该被转发、丢弃还是提交到协议枝上层。 而有时 ethl 也可能会作为报文的源地址或目的地址 直接参与报文的发送与接收,从而绕过网桥。

在这里插入图片描述

Iptables

我们知道, Linux 络协议樵非常高效,同时比较复杂 如果我们希望在数据的处理过程中对关心的数据进行一些操作该怎么做呢? Linux 提供了一套机制来为用户实现自定义的数据包处理过程。在 Linux 网络协议棋中有一组回调函数挂接点,通过这些挂接点挂接的钩子函数可以在 Linux 网络棋处理数据包的过程中对数据包进行 些操作,例如过滤、修改、丢弃等 整个挂接点技术叫作 Netfilter lptablesNetfilter 负责在内核中执行各种挂接的规则,运行在内核模式中:而 lptables 是在用户模式下运行的进程,负责协助维护内核中 Netfilter 的各种规则表 通过 者的配合来实现整个 Linux 网络协议战中灵活的数据包处理机制。

总结

network namespace 主要提供了关于网络资源的隔离,包括网络设备、IPv4 和 IPv6协议栈、IP 路由表、防火墙、/proc/net目录、/sys/class/net目录、端口(socket)等。

linux Bridge 功能相当于物理交换机,为连在其上的设备(容器)转发数据帧。如 docker0网桥。

iptables 主要为容器提供 NAT 以及容器网络安全。

veth pair 两个虚拟网卡组成的数据通道。在 Docker 中,用于连接 Docker 容器和 Linux Bridge。一端在容器中作为 eth0 网卡,另一端在 Linux Bridge 中作为网桥的一个端口。


Docker 网络模式

Docker使用 Linux 桥接的方式,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接 Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过-p-P 参数来启用,访问容器的时候就通过[宿主机 IP]:[容器端口]访问容器。

Docker 网络模型配置说明
host 模式–-network=host容器和宿主机共享 Network namespace
containe 模式--network=container:ID容器和另外一个容器共享 Network namespacekubernetes中的 pod 就是多个容器共享一个 Network namespace
none 模式--network=none容器有独立的 Network namespace,但并没有对其进行任何网络设置,如分配 veth pair 和网桥连接,配置IP 等。
bridge 模式--network=bridgeDocker 进程启动时,会在主机上创建一个名为 docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。(默认为该模式)

HOST 模式

如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用host模式的容器可以直接使用宿主机的 IP 地址与外界通信,容器内部的服务端口也可以使用宿主机的
端口,不需要进行NAThost最大的优势就是网络性能比较好,但是 docker host上已经使用的端口就不能再
用了,网络的隔离性不好。

在这里插入图片描述

[root@instance-gvpb80ao ~]# docker run -d --name my-web --network host nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
d121f8d1c412: Pull complete
ebd81fc8c071: Pull complete
655316c160af: Pull complete
d15953c0e0f8: Pull complete
2ee525c5c3cc: Pull complete
Digest: sha256:c628b67d21744fce822d22fdcc0389f6bd763daac23a6b77147d0712ea7102d0
Status: Downloaded newer image for nginx:latest
06941559a3f7e0c53cf228302dedc2040c10f2eb0b6e3d0f962c065b0e0419ce


[root@instance-gvpb80ao ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
06941559a3f7 nginx "/docker-entrypoint.…" 6 minutes ago
Up 6 minutes my-web


[root@instance-gvpb80ao ~]# curl 127.0.0.1:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Containe 模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

在这里插入图片描述

[root@instance-gvpb80ao ~]# docker run -itd --name test01 busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
df8698476c65: Pull complete
Digest: sha256:d366a4665ab44f0648d7a00ae3fae139d55e32f9712c67accd604bb55df9d05a
Status: Downloaded newer image for busybox:latest
dd99687d303d61d649364084ad353ec38b4e07149b0328301ec9691f18669951

[root@instance-gvpb80ao ~]# docker run -itd --name test02 --network "container:test01" busybox
72adb0dcdb93b6adc7a62e1ad1ac274f64b8cec941d5f89da43fcd0757f99fa3

[root@instance-gvpb80ao ~]# docker exec -it test02 sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:28 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2423 (2.3 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # exit
[root@instance-gvpb80ao ~]# docker exec -it test01 sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:29 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2493 (2.4 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #

none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置IP 等。

这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

在这里插入图片描述

[root@instance-gvpb80ao ~]# docker run -itd --name test03 --network none busybox
b9dde79754bc110314be4aecde1251dcdd6ce28fdf43102ae184b79c6e7414bc
[root@instance-gvpb80ao ~]# docker exec -it test03 sh
/ # ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

bridge 模式

Docker 进程启动时,会在主机上创建一个名为 docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

docker0 子网中分配一个 IP给容器使用,并设置 docker0IP 地址为容器的默认网关。在主机上创建
一对虚拟网卡 veth pair设备,Dockerveth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网
卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到 docker0网桥中。可以
通过brctl show 命令查看。

bridge模式是 docker的默认网络模式,不写--net参数,就是bridge模式。使用 docker run -p 时,docker
实际是在iptables 做了 DNAT 规则,实现端口转发功能。可以使用iptables -t nat -vnL 查看。

在这里插入图片描述

[root@instance-gvpb80ao ~]# docker run -itd --name test04 busybox
dd17d863b2957a29df44b2552365eb0cfc01552fd4ec6b8b63e28dfd0d61472e
[root@instance-gvpb80ao ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default
qlen 1000
link/ether fa:16:3e:4a:9c:c7 brd ff:ff:ff:ff:ff:ff
inet 172.16.0.4/20 brd 172.16.15.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe4a:9cc7/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group
default
link/ether 02:42:ab:42:6a:8a brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:abff:fe42:6a8a/64 scope link
valid_lft forever preferred_lft forever
5: veth870d996@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master
docker0 state UP group default
link/ether ae:36:24:dc:11:6d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::ac36:24ff:fedc:116d/64 scope link
valid_lft forever preferred_lft forever
7: veth6acb18a@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master
docker0 state UP group default
link/ether 4e:03:b1:5e:40:91 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::4c03:b1ff:fe5e:4091/64 scope link
valid_lft forever preferred_lft forever
[root@instance-gvpb80ao ~]# docker exec -it test04 bash
/ # ping 172.16.0.4
PING 172.16.0.4 (172.16.0.4): 56 data bytes
64 bytes from 172.16.0.4: seq=0 ttl=64 time=0.113 ms
64 bytes from 172.16.0.4: seq=1 ttl=64 time=0.101 ms
^C
--- 172.16.0.4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.101/0.107/0.113 ms


Dockerfile 构建镜像

Dockerfile 由一行行命令语句组成, 并且支持以#开头的注释行。一般而言, Dockerfile主体内容分为四部分:基础镜像信息、 维护者信息、 镜像操作指令和容器启动时执行指令。

Docker以从上到下的顺序运行 Dockerfile 的指令。为了指定基本映像,第一条指令必须是FROM。一个声明以#字符开头则被视为注释。可以在 Docker 文件中使用 RUNCMDFROMEXPOSEENV 等指令。

在这里插入图片描述

FROM:指定基础镜像,必须为第一个命令

格式:
FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>

示例: FROM mysql:5.6

注: tag 或 digest 是可选的,如果不使用这两个值时,会使用 latest 版本的基础镜像

MAINTAINER: 维护者信息

格式:
MAINTAINER <name>

示例:
MAINTAINER Jasper Xu
MAINTAINER sorex@163.com
MAINTAINER Jasper Xu <sorex@163.com>

RUN:构建镜像时执行的命令

RUN 用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell 执行
格式:
RUN <command>

exec 执行
格式:
RUN ["executable", "param1", "param2"]

示例:
RUN ["executable", "param1", "param2"]
RUN apk update
RUN ["/etc/execfile", "arg1", "arg1"]

注: 
RUN 指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache 参数,如:docker build --no-cache

ADD:将本地文件添加到容器中

tar 类型文件会自动解压(网络压缩资源不会被解压)

#格式:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"] 用于支持包含空格的路径

#示例:
ADD hom* /mydir/ # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/ # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/ # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # 添加 "test" 到 /absoluteDir/

COPY:功能类似 ADD,但是是不会自动解压文件,也不能访问网络资源

指令:COPY
功能描述:复制文件到镜像中

语法:COPY < src>< dest>|[< src>”,… “< dest>]

提示:指令逻辑和 ADD 十分相似,同样 Docker Daemon 会从编译目录寻找文件或目录,dest 为镜像中的绝对路径或者相对于 WORKDIR 的路径

CMD:构建容器后调用,也就是在容器启动时才进行调用

#格式:
CMD ["executable","param1","param2"] (执行可执行文件,优先)
CMD ["param1","param2"] (设置了 ENTRYPOINT,则直接调用 ENTRYPOINT 添加参数)
CMD command param1 param2 (执行 shell 内部命令)

#示例:
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]注: CMD 不同于 RUN,CMD 用于指定在容器启动时所要执行的命令,而 RUN 用于指定镜像构建时所要执行的命令。

LABEL:用于为镜像添加元数据

格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ... 

示例:
LABEL version="1.0" description="这是一个 Web 服务器" by="IT 笔录" 

注:
使用 LABEL 指定元数据时,一条 LABEL 指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条 LABEL 指令指定,以免生成过多的中间镜像。

ENV:设置环境变量

格式:
ENV <key> <value> #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
ENV <key>=<value> ... #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行

示例:
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat=fluffy

EXPOSE:指定于外界交互的端口

格式:
EXPOSE <port> [<port>...]

示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp

注:
EXPOSE 并不会让容器的端口访问到主机。要使其可访问,需要在 docker run 运行容器时通过-p 来发布这些端口,或通过-P 参数来发布 EXPOSE 导出的所有端口

VOLUME:用于指定持久化目录

格式:
VOLUME ["/path/to/dir"]

示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]

注: 
一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:
1 卷可以容器间共享和重用
2 容器并不一定要和其它容器共享卷
3 修改卷后会立即生效
4 对卷的修改不会对镜像产生影响
5 卷会一直存在,直到没有任何容器在使用它

WORKDIR:工作目录,类似于 cd 命令

格式:
WORKDIR /path/to/workdir

示例:
WORKDIR /a (这时工作目录为/a)
WORKDIR b (这时工作目录为/a/b)
WORKDIR c (这时工作目录为/a/b/c)

注:
通过 WORKDIR 设置工作目录后,Dockerfile 中其后的命令 RUN、CMD、ENTRYPOINT、ADD、COPY
等命令都会在该目录下执行。在使用 docker run 运行容器时,可以通过-w 参数覆盖构建时所设置的工作目录。

ARG:用于指定传递给构建运行时的变量

格式:
ARG <name>[=<default value>]

示例:
ARG site
ARG build_user=www

ONBUILD:用于设置镜像触发器

格式: 
ONBUILD [INSTRUCTION]

示例:
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

注:
当所构建的镜像被用做其它镜像的基础镜像,该镜像中的触发器将会被钥触发

Dockerfile 构建镜像案例

FROM centos7
MAINTAINER Alvin alvincy@qq.com
RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo
http://mirrors.aliyun.com/repo/Centos-7.repo
RUN yum makecache
RUN yum update -y
RUN yum install python3 -y
RUN pip3 install django
COPY docker /root/docker
WORKDIR /root/docker
EXPOSE 8080
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8080"]
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页