Docker 的 Logo 设计为蓝色鲸鱼,拖着许多集装箱。鲸鱼可看作为宿主机,集装箱可理解为相互隔离的容器,每个集装箱中都包含自己的应用程序。
Docker 的设计宗旨:Build,Ship and Run Any APP,Anywhere
即通过对应用组件的封装、发布、部署、运行等生命周期的管理,达到应用组件级别的一次封装,导出运行的目的。这里的组件,既可以是一个应用,也可以是一套服务,甚至是一个完整的操作系统。
容器化越来越受欢迎,因为容器有如下特点:
特性 | Docker 容器 | openstack 虚拟机 |
---|---|---|
部署难度 | 非常简单 | 组件多,部署复杂 |
启动速度 | 秒级 | 分钟级 |
执行性能 | 和物理系统几乎一致 | vm 会占用一些资源 |
镜像体积 | 镜像 MB 级别 | 虚拟机镜像 GB 级别 |
管理效率 | 管理简单 | 组件相互依赖,管理复杂 |
可管理性 | 单进程 | 完整的系统管理 |
网络连接 | 比较弱 | 借助 neutron 可以灵活组件各类网络管理 |
性能 | 接近原生(直接在内核中运行) | 50% 左右损失 |
系统支持量(单机) | 上千个 | 几十个 |
隔离性 | 进程级别 | 操作系统级别 |
封装程度 | 只打包项目代码和依赖关系,共享宿主机内核 | 完整的操作系统,与宿主机隔离 |
docker 本质就是宿主机的一个进程,docker 是通过 namespace 实现资源隔离,通过 cgroup 实现资源限制,通过写时复制技术 copy-on-write
实现了高效的文件操作(类似虚拟机的磁盘比如分配 500G 并不是实际占用物理磁盘 500G)。
namespace | 系统调用参数 | 隔离内容 |
---|---|---|
UTS | CLONE_NEWUTS | 主机名与域名 |
IPC | CLONE_NEWWIPC | 信号量、消息队列和共享内存 |
PID | CLONE_NEWPID | 进程编号 |
NETWORK | CLONE_NEWNET | 网络设备、网络栈、端口等 |
MOUNT | CLONE_NEWNS | 挂载点(文件系统) |
USER | CLONE_NEWUSER | 用户和用户组(3.8 以后的内核才支持) |
#环境配置
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
#安装依赖包
yum -y install yum-utils device-mapper-persistemt-data lvm2
#设置阿里云镜像源
cd /etc/yum.repos.d/
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装 docker-ce 社区版(企业版叫 docker-ee,收费)
yum -y install docker-ce
#启动
systemctl enable docker && systemctl start docker
配置阿里云镜像加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://4iv7219l.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
网络优化
cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_forward=1
EOF
sysctl -p
systemctl restart network
systemctl restart docker
一键安装
[root@c7-1 ~]#cat docker.sh
#!/bin/bash
#环境配置
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
#安装依赖包
yum -y install yum-utils device-mapper-persistemt-data lvm2
#设置阿里云镜像源
cd /etc/yum.repos.d/
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装 docker-ce 社区版(企业版叫 docker-ee,收费)
yum -y install docker-ce
#配置阿里云镜像加速(尽量使用自己的)
#地址 https://help.aliyun.com/document_detail/60750.html
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://4iv7219l.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
#网络优化
cat >> /etc/sysctl.conf <<EOF
net.ipv4.ip_forward=1
EOF
sysctl -p
systemctl restart network
systemctl enable docker && systemctl restart docker
PS
docker-server 端配置文件 daemon.json
#生产配置示例,在 daemon.json 中定义
{
"graph": "/data/docker",
"storage-driver": "overlay2",
"insecure-registries": ["registry.access.redhat.com","quary.io"]
"registry-mirrors": ["https://q"]
"bip": "172.7.5.1/24",
"exec-opts": ["native.cgroupdriver=systemd"],
"live-restore": true
}
#参数说明
"graph": "/data/docker", #指定数据目录
"storage-driver": "overlay2", #指定存储引擎
"insecure-registries": ["registry.access.redhat.com","quary.io"] #私有仓库
"registry-mirrors": ["https://q"] #配置镜像加速
"bip": "172.7.5.1/24", #docker 网络,中间两位建议和宿主机一样,容器有问题好定位在哪个宿主机
"exec-opts": ["native.cgroupdriver=systemd"], #启动时候的额外参数(驱动,k8s使用)
"live-restore": true #当docker容器引擎挂掉的时候,使用docker跑起来的容器还能运行(分离)
PS:
- docker client 客户端连接到了服务端(服务端是以一个守护进程的形式跑在操作系统里面的)restful api 典型的 C/S 架构
- 由 docker 服务端的守护进程从 docker hub 上下载了镜像(PS:服务端会先检查本地系统是否有这个镜像)
- 服务端创建了一个新的容器,然后从拉去的这个镜像启动了一个容器,容器执行了脚本/可执行程序让我们可以查看/使用
- docker 服务端把这些信息流(传递)返回到客户端并展示出来(展示在终端上)
#查询 docker 版本和信息
docker version
docker info
#搜索镜像(可以自己制作镜像上传本地或官网仓库 dockerfile)
docker search <镜像名>
#下载镜像
docker pull <镜像名>
#查看镜像列表
docker images
#查看镜像详细信息
docker inspect <镜像 ID>
#给镜像打标签
docker tag <镜像名>:<原标签> <镜像名>:<新标签>
#docker tag nginx:latest nginx:lnmp
#删除镜像
docker rmi <镜像名>
docker rmi <镜像标签>
docker rmi <镜像 ID>
docker rmi `docker images -aq` #删除所有镜像
docker images | awk 'NR>=2{print "docker rmi -f "$3}' | bash
#镜像导出
docker save -o <导出的文件名> <镜像名>
#docker save -o nginx_v1 nginx:latest
#镜像导入
docker load < [镜像文件]
#docker load < nginx_v1
#查询容器
docker ps -a
#查看容器占用系统资源信息
docker stats
#创建容器
docker create -it nginx:latest /bin/bash
#常用参数说明
> -i 让容器的标准输入保持打开
> -t 分配一个伪终端
> -d 以后台守护进程的方式运行
#开启/停止/重启 容器
docker start <容器 ID>
docker stop <容器 ID>
docker restart <容器 ID>
#后台运行,指定容器名称为 test
docker run -itd --name test nginx:latest /bin/bash
#进入容器
docker exec -it <容器 ID> /bin/bash #exit 退出
#容器 导出/导入
docker export [容器 ID] > [文件名]
docker import [容器文件名] [指定镜像名称] #导入的是镜像
#批量停止容器
docker ps -a | awk 'NR>=2{print "docker stop "$1}' | bash
docker ps -a | awk 'NR>=2{print $1}' | xargs docker stop
#批量删除容器
docker rm -f `docker ps -aq`
docker ps -a | awk 'NR>=2{print "docker rm "$1}' | bash
docker ps -a | awk 'NR>=2{print $1}' | xargs docker rm -f
#批量删除 "exit" 状态(指定状态)的容器
for i in `docker ps -a | grep -i exit | awk '{print $1}'`; do docker rm -f $i;done
#查看容器进程号
docker inspect -f '{
{.State.Pid}}' <容器名>
docker inspect -f '{
{.State.Pid}}' <容器 ID>
容器与宿主机之间文件的复制
docker run -itd --name nginx_test nginx:latest /bin/bash
#主机复制到容器
[root@tengxun-02 ~]#touch testfile
[root@tengxun-02 ~]#ls
testfile
[root@tengxun-02 ~]#docker cp testfile nginx_test:/opt
[root@tengxun-02 ~]#docker exec -it nginx_test bash
root@2ca07b152329:/# cd /opt
root@2ca07b152329:/opt# ls
testfile
#容器复制到主机
root@2ca07b152329:/opt# ls
testfile
root@2ca07b152329:/opt# touch haha
root@2ca07b152329:/opt# ls
haha testfile
root@2ca07b152329:/opt# exit
exit
[root@tengxun-02 ~]#docker cp nginx_test:/opt/haha .
[root@tengxun-02 ~]#ls
haha testfile
进入容器没有 systemctl 命令解决
添加 --privileged=true(指定此容器是否为特权容器),使用此参数,则不能用 attach。
> 示例:
docker run -itd --name test3 --privileged=true centos /sbin/init
`/sbin/init 内核启动时主动呼叫的第一个进程`
可以使用 docker inspect <容器ID>
docker ps -a
docker exec -it <容器ID> /bin/bash
yum install httpd -y
systemctl status httpd
docker 在后台的标准运行过程:
(1)检查本地是否存在指定的镜像。当镜像不存在时,会从公有仓库下载;
(2)利用镜像创建并启动一个容器;
(3)分配一个文件系统给容器,在只读的镜像层外面挂载一层可读写层;
(4)从宿主主机配置的网桥接口中桥接一个虚拟机接口到容器中;
(5)分配一个地址池中的IP地址给容器;
(6)执行用户指定的应用程序,执行完毕后容器被终止运行。
Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个容器时会根据 Docker 网络的网段分配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。
[root@huawei-01 ~]#ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:2e:57:4a:09 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
..........
[root@huawei-01 ~]#docker run -itd --name nginx_01 nginx:latest /bin/bash
7fc40ddb606d02a42ef613bd5357fb1c1ff3f2cd75d693b07ec2b763a227a3ee
[root@huawei-01 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7fc40ddb606d nginx:latest "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 80/tcp nginx_01
[root@huawei-01 ~]#docker inspect 7fc40ddb606d
..........
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "3b3ea8498805a90c4c69dcc48e37253aada9c91222023ad7e3ca5584efd1c659",
"EndpointID": "bfa5118a2999e5ae6bb2e9fb30303627a1b163470416c810ef22cfc073638d1f",
"Gateway": "172.17.0.1", #docker0 的 IP 作为容器网关
"IPAddress": "172.17.0.2", #容器 IP 实现容器内部通信
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
Docker 网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过 Container-IP 访问到容器。如果希望容器能够被外部网络访问到,可以通过 映射容器端口到宿主主机(端口映射)
,即 docker run 创建容器时通过 -p | -P
参数来启用,访问容器的时候就通过 [宿主机 IP]:[容器端口]
访问容器。
PS:
- -P 将容器内部开放的网络端口随机映射到宿主机的一个端口上;
- -p 指定要映射的端口,一个指定端口上只可以绑定一个容器。支持的格式如下:
IP:HOSTPORT:CONTAINERPORT:指定 ip、指定宿主机 port、指定容器 port
适用于映射到指定地址的指定端口
eg:将容器的 5000 端口映射到指定地址 127.0.0.1 的 5000 端口上
docker run -itd -p 127.0.0.1:5000:5000 docker.io/centos:latest /bin/bash
[root@tengxun-02 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@tengxun-02 ~]#docker run -itd --name nginx_01 -p 8080:80 nginx:latest /bin/bash
540cc92956a8bc393da393d3a53c78ee7fd314ea2049994be04e994af59d7f8a
[root@tengxun-02 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
540cc92956a8 nginx:latest "/bin/bash" 12 seconds ago Up 12 seconds 0.0.0.0:8080->80/tcp nginx_01
[root@tengxun-02 ~]#docker exec -it 540cc92956a8 /bin/bash -c nginx
2021/11/26 08:07:00 [notice] 7#7: using the "epoll" event method
2021/11/26 08:07:00 [notice] 7#7: nginx/1.21.4
2021/11/26 08:07:00 [notice] 7#7: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2021/11/26 08:07:00 [notice] 7#7: OS: Linux 3.10.0-1160.11.1.el7.x86_64
2021/11/26 08:07:00 [notice] 7#7: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2021/11/26 08:07:00 [notice] 13#13: start worker processes
2021/11/26 08:07:00 [notice] 13#13: start worker process 14
2021/11/26 08:07:00 [notice] 13#13: start worker process 15
[root@tengxun-02 ~]#netstat -antp |grep 8080
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 5877/docker-proxy
[root@tengxun-02 ~]#netstat -antp |grep 80
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 5877/docker-proxy
tcp 0 0 10.0.24.9:22 180.111.206.87:24590 ESTABLISHED 476/sshd: root@pts/
tcp 0 52 10.0.24.9:22 180.111.206.87:23724 ESTABLISHED 25140/sshd: root@pt
tcp 0 0 10.0.24.9:54800 169.254.0.138:8086 ESTABLISHED 16932/tat_agent
测试访问(云主机需在防火墙配置规则)
[root@tengxun-02 ~]#curl 49.232.8.65:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
color-scheme: light dark; }
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>
注意:
IP:HOSTPORT:CONTAINERPORT
指定 ip、指定宿主机 port、指定容器 port
0.0.0.0:8080->80/tcp
外网是无法访问容器内的 80 端口的,将容器的 80 端口映射到宿主机的 8080 端口上,外网就可以通过宿主机的 8080 端口访问容器内的应用服务。
docker 端口映射
网络模式 | 说明 |
---|---|
Host | 容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。 |
Container | 创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围。 |
None | 该模式关闭了容器的网络功能。 |
Bridge | 默认为该模式,此模式会为每一个容器分配、设置 IP 等,并将容器连接到一个 Docker0 虚拟网桥,通过 docker0 网桥以及 iptables nat 表配置与宿主机通信。 |
自定义网络 | 自定义网络后,可指定容器 IP |
安装 Docker 时,它会自动创建三个网络:bridge(创建容器默认连接到此网络)、none、host。
[root@tengxun-02 ~]#docker network ls
NETWORK ID NAME DRIVER SCOPE
d1c5e817b704 bridge bridge local
79d2533e9fb2 host host local
c209ac067e43 none null local
[root@tengxun-02 ~]#docker network list
NETWORK ID NAME DRIVER SCOPE
d1c5e817b704 bridge bridge local
79d2533e9fb2 host host local
c209ac067e43 none null local
Docker 内置(bridge、host、none)三个网络,运行容器时可以使用 --net | --network
标志来指定容器应连接到哪些网络。如不指定,docker 守护程序默认将容器连接到 bridge 网络。
- host 模式:使用 --net=host 指定
- none 模式:使用 --net=none 指定
- container 模式:使用 --net=container:NAME_or_ID 指定
- bridge 模式:使用 --net=bridge 指定(默认设置,可省略)
相当于 Vmware 中的桥接模式,与宿主机在同一个网络中,但没有独立 IP 地址。Docker 使用了 Linux 的 Namespaces 技术来进行资源隔离,如 PID Namespace 隔离进程,Mount Namespace 隔离文件系统,Network Namespace 隔离网络等。
一个 Network Namespace 提供了一份独立的网络环境,包括网卡、路由、iptable 规则等都与其他的 Network Namespace 隔离。一个 Docker 容器一般会分配一个独立的 Network Namespace。但如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡、配置自己的 IP 等,而是使用宿主机的 IP 和端口。
[root@huawei-01 ~]#docker run -itd --name nginx_01 --net=host nginx:latest bash
9d9892111b13dc8dd352b04997202fbef575fbee32694047783d363c34a2997f
[root@huawei-01 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9d9892111b13 nginx:latest "/docker-entrypoint.…" 4 seconds ago Up 3 seconds nginx_01
[root@huawei-01 ~]#docker inspect -f '{
{.State.Pid}}' nginx_01 #查看容器进程
3448
[root@huawei-01 ~]#ll /proc/3448/ns #查看容器的进程、网络、文件系统等命名空间编号
total 0
lrwxrwxrwx 1 root root 0 Nov 26 16:58 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 ipc -> ipc:[4026532523]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 mnt -> mnt:[4026532521]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 net -> net:[4026531888]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 pid -> pid:[4026532524]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 pid_for_children -> pid:[4026532524]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 16:58 uts -> uts:[4026532522]
[root@huawei-01 ~]#docker run -itd --name nginx_02 --net=host nginx:latest bash
0550d4df0634f6c4c859b56818f26dd9c0b2d6470543d3414085744de050812b
[root@huawei-01 ~]#docker inspect -f '{
{.State.Pid}}' nginx_02
3526
[root@huawei-01 ~]#ll /proc/3526/ns
total 0
lrwxrwxrwx 1 root root 0 Nov 26 17:01 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 ipc -> ipc:[4026532527]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 mnt -> mnt:[4026532525]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 net -> net:[4026531888]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 pid -> pid:[4026532528]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 pid_for_children -> pid:[4026532528]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Nov 26 17:01 uts -> uts:[4026532526]
# net 与 user 的命名空间相同,host 模式与系统共享 IP
这个模式指定新容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
[root@docker ~]# docker run -itd --name test1 centos:7 bash
16cfef748ce1e1653e19925b6c38b28f70ebadb85a4ff5c8913befe1d1b6a7e9
[root@docker ~]# docker inspect -f '{
{.State.Pid}}' test1
5428
[root@docker ~]# ls -l /proc/5428/ns
总用量 0
lrwxrwxrwx 1 root root 0 10月 11 16:18 ipc -> ipc:[4026532578]
lrwxrwxrwx 1 root root 0 10月 11 16:18 mnt -> mnt:[4026532576]
lrwxrwxrwx 1 root root 0 10月 11 16:13 net -> net:[4026532581]
lrwxrwxrwx 1 root root 0 10月 11 16:18 pid -> pid:[4026532579]
lrwxrwxrwx 1 root root 0 10月 11 16:18 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 10月 11 16:18 uts -> uts:[4026532577]
[root@docker ~]# docker run -itd --name test2 --net=container:test1 centos:7 bash
477032acba96fa0f4adb590a6846792fa99615e2eb9744e250cf14a9d7092a53
[root@docker ~]# docker inspect -f '{
{.State.Pid}}' test2
5597
[root@docker ~]# ls -l /proc/5597/ns
总用量 0
lrwxrwxrwx 1 root root 0 10月 11 16:20 ipc -> ipc:[4026532699]
lrwxrwxrwx 1 root root 0 10月 11 16:20 mnt -> mnt:[4026532697]
lrwxrwxrwx 1 root root 0 10月 11 16:20 net -> net:[4026532581]
lrwxrwxrwx 1 root root 0 10月 11 16:20 pid -> pid:[4026532700]
lrwxrwxrwx 1 root root 0 10月 11 16:20 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 10月 11 16:20 uts -> uts:[4026532698]
# net 与 user 的命名空间相同,container 模式之间共享 IP
使用 none 模式,Docker 容器拥有自己的 Network Namespace,但是并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。这种网络模式下容器只有 lo 回环网络,没有其他网卡。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
bridge 模式是 docker 的默认网络模式,不用 --net 参数默认 bridge 模式。
相当于 Vmware 中的 nat 模式,容器使用独立 Network Namespace,并连接到 docker0 虚拟网卡。通过 docker0 网桥以及 iptables nat 表配置与宿主机通信,此模式会为每一个容器分配 Network Namespace、设置 IP 等,并将一个主机上的 Docker 容器连接到一个虚拟网桥上。
[root@docker ~]# docker run -itd --name test1 -P centos:7 bash
92f615aecf1e9e22956446536db4bcfa91d2ce94dd9e3e9253c40a5e1d2b0fde
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
92f615aecf1e centos:7 "bash" 15 seconds ago Up 14 seconds test1
[root@docker ~]# iptables -t nat -vnL
······
Chain POSTROUTING (policy ACCEPT 531 packets, 39905 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
······
直接使用 bridge 模式是无法支持指定 IP 运行 docker 的,例如执行以下命令就会报错:
[root@docker ~]# docker run -itd --name test1 --network=bridge --ip 172.17.0.8 centos:7 bash
0e1c5c2a0ed99d3e857dbf9a42046c670235d4eac4a5aa2690e4d7ce703cca5e
docker: Error response from daemon: user specified IP address is supported on user defined networks only.
# IP 错误,无法使用
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0e1c5c2a0ed9 centos:7 "bash" About a minute ago Created test1
[root@docker ~]# docker start test1
Error response from daemon: user specified IP address is supported on user defined networks only
Error: failed to start containers: test1
# IP 错误,无法启动
可以先自定义网络,再使用指定 IP 运行 docker 容器
[root@c7-1 ~]#docker network create --subnet=172.111.0.0/16 --opt "com.docker.network.bridge.name"="docker" mynetwork
3452df02a82449b29199394483d6c99a4c9c3406c3ffdbf588240de6a508e9d6
[root@c7-1 ~]#ifconfig
docker: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.111.0.1 netmask 255.255.0.0 broadcast 172.111.255.255
ether 02:42:a7:15:d0:34 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
······
[root@c7-1 ~]#docker network ls
NETWORK ID NAME DRIVER SCOPE
a4f6af884c35 bridge bridge local
9397ae985a66 host host local
3452df02a824 mynetwork bridge local
3d49189a111f none null local
[root@c7-1 ~]#docker run -itd --name centos-01 --net mynetwork --ip 172.111.0.11 centos:7 bash
d45b5b5a400245c8f280796c5286eeced9b7959bdfa2fb0a9d50d38b5c89224b
[root@c7-1 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d45b5b5a4002 centos:7 "bash" 13 seconds ago Up 12 seconds centos-01
5c6260be004b hello-world "/hello" 2 days ago Exited (0) 2 days ago goofy_haslett
[root@c7-1 ~]#docker exec -it centos-01 bash
[root@d45b5b5a4002 /]# ifconfig
bash: ifconfig: command not found
[root@d45b5b5a4002 /]# yum -y install net-tools
[root@d45b5b5a4002 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.111.0.11 netmask 255.255.0.0 broadcast 172.111.255.255
ether 02:42:ac:6f:00:0b txqueuelen 0 (Ethernet)
RX packets 5846 bytes 19765435 (18.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3947 bytes 216686 (211.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 69 bytes 6309 (6.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 69 bytes 6309 (6.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
总结
#查看网络列表
docker network ls
#查看容器信息(包含配置、环境、网关、挂载、cmd 等信息)
docker inspect <容器 ID>
#指定分配容器 IP 地址
docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash
#以上会报错
#自定义网络固定 IP
docker network create --subnet=172.18.0.0/16 mynetwork
docker run -itd --name test2 --net mynetwork --ip 172.18.0.100 centos:latest /bin/bash
#暴露端口
> -p 自定义端口(宿主机端口:容器内端口)
> -P 随机瑞口( -P 随机端口范围 49153-65535)
docker run -itd -p 333:80 nginx /bin/bash (docker 0)
docker run -itd -P nginx /bin/bash
#在宿主机环境执行容器内命令
docker exec -it <容器ID> /bin/bash -c 'nginx' #启动 nginx
docker exec <容器ID/容器name> 执行的命令
管理 Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器(Data Volumes Containers)。
数据卷是一个供容器使用的特殊目录,位于容器中。可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻可见,并且更新数据不会影响镜像,从而实现数据在宿主机与容器之间的迁移。数据卷的使用类似于 Linux 下对目录进行的 mount 操作。
如果需要在容器之间共享一些数据,最简单的方法就是使用数据卷容器。数据卷容器是一个普通的容器,专门提供数据卷给其他容器挂载使用。
数据卷(容器和宿主机共享文件)
docker pull centos
#宿主机目录 /var/www 挂载容器中的 /data1
docker run -v /var/www:/data1 --name web1 -it centos /bin/bash
[roote202dd484fd62 / ]#cd /data1/
[root@202dd484fd62 data1]# touch test123
#返回宿主机进行查看
[root@localhost ~]#ls /var/www/
#应用场景
原理:将容器内部的配置文件目录,挂载到宿主机指定目录下。
作用:
① 修改配置文件例如:nginx.conf /usr/local/nginx/conf/nginx.conf ---> /container_nginx/conf/nginx.conf
② 容器内部产生的日志,如何收集将容器内部存放日志文件的目录挂载到宿主机指定目录下 /container_nginx/log/access_log/access_log
③ 传入变量挂载到宿主机在宿主机上添加变量内容,将变量放入共享目录,在容器中 /etc/profile 直接加载就可以
export xxdir=/data/data1/xx-
数据卷容器(容器之间共享文件)
#数据卷容器
docker run --name web100 -v /data1 -v /data2 -itd centos /bin/bash
#新容器挂载数据卷容器 web100
docker run -itd --volumes-from web100 --name db1 centos /bin/bash
> 原理:让两个容器实现数据共享
php --> mysql 之间想要通讯借助于 socket 通讯文件
示例:
#创建容器并创建两个目录
[root@tengxun-02 ~]#docker run --name web100 -v /data1 -v /data2 -itd centos:7 /bin/bash
0f182c3e3a35bed01f3063a765ba553fafb4995d823709f7902e55ea42877910
#将 web100 容器的两个目录和新创建的 db1 容器共享
[root@tengxun-02 ~]#docker run -itd --volumes-from web100 --name db1 centos:7 /bin/bash
ac2cb6a53d98e2d0e80370da514fd7b7373729fcaa8e1c211df5faf288483a3f
[root@tengxun-02 ~]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ac2cb6a53d98 centos:7 "/bin/bash" 3 seconds ago Up 2 seconds db1
0f182c3e3a35 centos:7 "/bin/bash" 10 seconds ago Up 9 seconds web100
[root@tengxun-02 ~]#docker exec -it db1 bash
[root@ac2cb6a53d98 /]# ls /
anaconda-post.log `data1` dev home lib64 mnt proc run srv tmp var
bin `data2` etc lib media opt root sbin sys usr
docker run -itd -P --name web1 centos:7 /bin/bash #创建并运行容器取名 web1,端口号自动映射
docker run -itd -P --name web2 --link web1:web1 centos:7 /bin/bash #创建并运行容器取名 web2,链接到 web1 和其通信
> 进 web2 容器,ping web1
--link 的格式:
--link <name or id>:alias
其中,name 和 id 是源容器的 name 和 id,alias 是源容器在 link 下的别名。
[root@docker www]# docker run -d --name test1 -P nginx
0a07519f54de9552a37d076613f9f5af4ff4b80d1d3c258762c45f876a29500b
[root@docker www]# docker run -d --name test2 -p 11111:80 nginx
9316ffd9e2aa98e8d1ea679128d308fc0f1842d854e8b772c7cd5c07647251a8
[root@docker www]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9316ffd9e2aa nginx "/docker-entrypoint.…" 1 second ago Up 1 second 0.0.0.0:11111->80/tcp, :::11111->80/tcp test2
0a07519f54de nginx "/docker-entrypoint.…" 19 seconds ago Up 18 seconds 0.0.0.0:49154->80/tcp, :::49154->80/tcp test1
[root@docker www]# curl http://192.168.122.10:11111
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
color-scheme: light dark; }
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>
[root@docker www]# curl http://192.168.122.10:49154
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html {
color-scheme: light dark; }
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>
创建镜像有三种方法:
启动一个镜像,在容器中做修改
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 87a94228f133 28 hours ago 133MB
centos 7 eeb6ee3f44bd 3 weeks ago 204MB
[root@docker ~]# docker create -it --name test1 centos:7 bash
ae03a782eb8fed80190bfee1c5e459c1e82e1406a55627553e93edc943645217
[root@docker ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae03a782eb8f centos:7 "bash" 2 seconds ago Created test1
将修改后的容器提交为新的镜像,需要使用该容器的 ID 号创建新镜像
[root@docker ~]# docker commit -m "new" -a "centos" test1 centos:test1
sha256:3e6e91b628effd49a7fa8fea422057cb392c76e852b2d60f9d7287bfa172ff88
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos test1 3e6e91b628ef 10 seconds ago 204MB
nginx latest 87a94228f133 28 hours ago 133MB
centos 7 eeb6ee3f44bd 3 weeks ago 204MB
commit 常用选项:
-m:说明信息
-a:作者信息
-p:生成过程中停止容器的运行
通过导入操作系统模板文件可以生成镜像,模板可以从 OPENVZ 开源项目下载,下载地址:
http://openvz.org/Download/template/precreated
[root@docker ~]# wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz
[root@docker ~]# cat debian-7.0-x86-minimal.tar.gz | docker import - debian:test
sha256:f7fd702b88cc14fbcc011dc0883edbf45dca3de99b0aef3fc8d184544c07fb5b
[root@docker ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
debian test f7fd702b88cc 36 seconds ago 215MB
centos test1 3e6e91b628ef About an hour ago 204MB
nginx latest 87a94228f133 29 hours ago 133MB
centos 7 eeb6ee3f44bd 3 weeks ago 204MB
URL 下载方式:
方法一:
wget 下载路径 -O 保存路径
方法二:
curl -L 下载路径 -o 保存路径
载入选项:
通过 docker save 导出的镜像,使用 docker load 导入 docker
通过 docker export 导出的容器,使用 docker import 导入 docker
Docker 镜像创建之 — dockerfile 详解