docker
文章目录
一、基础
- 配置docker的yum源
[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
gpgcheck=0
[centos]
name=extras
baseurl=https://mirrors.aliyun.com/centos/7/extras/x86_64
gpgcheck=0
- 修改配置,开机自启
[root@localhost ~]# systemctl enable --now docker.service
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
- 基本命令
[root@localhost ~]# docker search kaminskypavel/mario
[root@localhost ~]# docker pull kaminskypavel/mario
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
kaminskypavel/mario latest 9a35a9e43e8c 7 years ago 198MB
[root@localhost ~]# docker history kaminskypavel/mario
IMAGE CREATED CREATED BY SIZE COMMENT
9a35a9e43e8c 7 years ago /bin/sh -c #(nop) CMD ["python3" "-m" "http.… 0B
<missing> 7 years ago /bin/sh -c #(nop) EXPOSE 8080/tcp 0B
<missing> 7 years ago /bin/sh -c #(nop) WORKDIR /app 0B
<missing> 7 years ago /bin/sh -c #(nop) COPY dir:02930d36f63824e72… 9.81MB
<missing> 7 years ago /bin/sh -c apt-get install -y python3 0B
<missing> 7 years ago /bin/sh -c #(nop) MAINTAINER Pavel 'PK' Kami… 0B
<missing> 7 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 7 years ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$… 1.9kB
<missing> 7 years ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/poli… 195kB
<missing> 7 years ago /bin/sh -c #(nop) ADD file:5a3f9e9ab88e725d6… 188MB
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4a7d913c032b kaminskypavel/mario "python3 -m http.ser…" 2 minutes ago Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp, 8080/tcp mariogame
[root@localhost ~]# docker rm -f 4a7d913c032b
4a7d913c032b
- 出现报错
[root@localhost ~]# docker run -d -p 9002:8080 --name mariogame --restart=always kaminskypavel/mario
e6900ab772fb7b46c8af3cc240b21b193146eaa1e7c06cc350c35649f5d3be1e
docker: Error response from daemon: driver failed programming external connectivity on endpoint mariogame (b6eca333313045bc9b8d93808c88c64b0ca233792b638149cba8bcae8b035cbd): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9002 -j DNAT --to-destination 172.17.0.2:8080 ! -i docker0: iptables: No chain/target/match by that name.
(exit status 1)).
[root@localhost ~]# docker inspect mariogame
# 发现容器没有正常获取到IP
# iptables也没有策略
[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
# 重启docker服务
[root@localhost ~]# systemctl restart docker.service
# 再看iptables有策略了
[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
# 再次启动容器
[root@localhost ~]# docker run -d -p 9002:8080 --name mariogame --restart=always kaminskypavel/mario
075662a4ff79bb4b1035f458d223675ba955042874cb5427ee6d5f73265e69b5
- 效果
二、镜像和容器
- 概念
-
- 共享宿主机内核
-
- base镜像提供最小的linux发行版
-
- 容器层以下所有镜像层都是只读的
-
- docker从上往下依次查找文件
-
- 容器层保存镜像变化的部分,并不对镜像进行改变
-
- 一个镜像最多127层
-
- 容器实际上就是宿主机中的一个进程
- 构建镜像
-
- commit构建
# 运行容器、修改容器、将容器保存为新镜像
## 运行容器
[root@localhost ~]# docker run -it --name demo busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
205dae5015e7: Pull complete
Digest: sha256:7b3ccabffc97de872a30dfd234fd972a66d247c8cfc69b0550f276481852627c
Status: Downloaded newer image for busybox:latest
/ #
/ # ll
sh: ll: not found
/ # ls
bin dev etc home lib lib64 proc root sys tmp usr var
/ # touch demo1
/ # touch demo2
/ # ls
bin demo1 demo2 dev etc home lib lib64 proc root sys tmp usr var
/ #
## ctrl+D退出容器,资源回收;ctrl+pq后台挂起容器
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eda375abd277 busybox "sh" About a minute ago Exited (0) 31 seconds ago demo
[root@localhost ~]# docker start demo
demo
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eda375abd277 busybox "sh" 3 minutes ago Up 5 seconds demo
075662a4ff79 kaminskypavel/mario "python3 -m http.ser…" 10 hours ago Up 10 hours 0.0.0.0:9002->8080/tcp, :::9002->8080/tcp mariogame
## 连接到后台容器
[root@localhost ~]# docker attach demo
/ #
/ #
/ # read escape sequence
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eda375abd277 busybox "sh" 4 minutes ago Up 44 seconds demo
## 修改容器,保存为新镜像
[root@localhost ~]# docker commit -m "add files" demo demo:v1
sha256:c0e76e51827a83de913a969284eff211fac9f6459acbbb478c5a7c756151ec65
[root@localhost ~]# docker history demo:v1
IMAGE CREATED CREATED BY SIZE COMMENT
c0e76e51827a 34 seconds ago sh 33B add files
66ba00ad3de8 13 days ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 13 days ago /bin/sh -c #(nop) ADD file:4bd5aa84616ee9384… 4.87MB
## 查看日志
[root@localhost docker]# docker logs nginxv1
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/01/17 05:31:00 [notice] 1#1: using the "epoll" event method
2023/01/17 05:31:00 [notice] 1#1: nginx/1.23.3
2023/01/17 05:31:00 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/01/17 05:31:00 [notice] 1#1: OS: Linux 3.10.0-957.el7.x86_64
2023/01/17 05:31:00 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 65536:65536
2023/01/17 05:31:00 [notice] 1#1: start worker processes
2023/01/17 05:31:00 [notice] 1#1: start worker process 29
效率低、难复现、易出错、使用者无法进行安全审计
-
- 使用DockerFile构建
-
-
- 1、Dockerfile会打包所在目录及子目录
-
-
-
- 2、常用命令:FROM(base镜像)、MAINTAINER(作者信息)、COPY(使用相对路径,原封不动)、ADD(也是拷贝,自解压,可下载远端URL)、ENV(环境变量)、EXPOSE(暴露服务接口)、VOLUME(申明数据卷,通常是挂载点,用于容器内数据的持久化)、WORKDIR(为RUN、CMD、ENTRYPOINT、ADD和COPY设定工作目录,会自动创建)、RUN(在容器里执行shell指令)、CMD和ENTRYPOINT(都用于设置容器启动后执行的命令,CMD会被RUN覆盖,ENTRYPOINT一定会执行,只有最后一个ENTRYPOINT有效)
-
-
- 扩展nginx镜像
# 创建Dockerfile
[root@localhost docker]# vim Dockerfile
FROM nginx
COPY index.html /usr/share/nginx/html
# 创建测试页
[root@localhost docker]# vim index.html
[root@localhost docker]# docker build -t nginx:v1 .
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM nginx
---> a99a39d070bf
Step 2/2 : COPY index.html /usr/share/nginx/html
---> a9734cbb4a63
Successfully built a9734cbb4a63
Successfully tagged nginx:v1
[root@localhost docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v1 a9734cbb4a63 5 seconds ago 142MB
demo v1 c0e76e51827a 13 minutes ago 4.87MB
nginx latest a99a39d070bf 5 days ago 142MB
# 开启容器
[root@localhost docker]# docker run -d -p 80:80 --name nginxv1 nginx:v1
e7866b65faf7e4d0cb773e890588375cbee3bd96e91edb4ea1d1e0ef258637a9
效果如下:
三、Docker仓库
- Docker Hub
-
- 需要网络,速度慢
-
- 所有人都可以访问
-
- 处于安全考量,镜像不能暴露在外网
- Docker本地仓库
-
- 官方配置文档:https://docs.docker.com/registry/deploying/
# 下载registry镜像,并启动
[root@localhost docker]# docker pull registry
[root@localhost docker]# docker run -d -p 5000:5000 --restart=always --name registry registry
# push镜像
[root@localhost docker]# docker tag nginx:v1 localhost:5000/nginx:v1
[root@localhost docker]# docker push localhost:5000/nginx:v1
# pull镜像
[root@localhost docker]# docker pull localhost:5000/nginx:v1
-
- 非安全本地仓库
vim /etc/docker/daemon.json
{
"insecure-registries" : ["myregistrydomain.com:5000"] # 填docker本地仓库服务器域名
}
-
- 安全本地仓库
# 删除非安全仓库,并移除卷
[root@docker1 ~]# docker rm -f registry
registry
[root@docker1 ~]# docker volume ls
DRIVER VOLUME NAME
local cb60a059934b5bd020c7499c7d6e2df46dd1833189b18490ddc2d62c9c60e583
[root@docker1 ~]# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
cb60a059934b5bd020c7499c7d6e2df46dd1833189b18490ddc2d62c9c60e583
Total reclaimed space: 56.88MB
[root@docker1 ~]# docker volume ls
DRIVER VOLUME NAME
# 创建自签名证书
## 安装openssl11,下载地址:
## https://kojipkgs.fedoraproject.org//packages/openssl11/1.1.1k/2.el7/x86_64/openssl11-1.1.1k-2.el7.x86_64.rpm
## https://kojipkgs.fedoraproject.org//packages/openssl11/1.1.1k/2.el7/x86_64/openssl11-libs-1.1.1k-2.el7.x86_64.rpm
[root@docker1 ~]# yum install -y openssl11-libs-1.1.1k-2.el7.x86_64.rpm openssl11-1.1.1k-2.el7.x86_64.rpm
[root@docker1 ~]# openssl11 req -newkey rsa:4096 -nodes -sha256 -keyout certs/repo.docker.alexw.com.key --addext "subjectAltName=DNS:repo.docker.alexw.com" -x509 -days 365 -out certs/repo.docker.alexw.com.crt
Generating a RSA private key
...................................................................................++++
............................................................................................++++
writing new private key to 'certs/repo.docker.alexw.com.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:shaanxi
Locality Name (eg, city) [Default City]:xi'an
Organization Name (eg, company) [Default Company Ltd]:alexw
Organizational Unit Name (eg, section) []:alexw
Common Name (eg, your name or your server's hostname) []:repo.docker.alexw.com
Email Address []:
# 运行容器,并挂载签名文件路径
[root@docker1 ~]# docker run -d -p 443:443 --restart=always --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/repo.docker.alexw.com.crt -e REGISTRY_HTTP_TLS_KEY=/certs/repo.docker.alexw.com.key registry
36f9d1862f07c668777560cc2caceb4a3312cf13321e0f23bf374c076eea450d
[root@docker1 ~]# docker tag nginx:latest repo.docker.alexw.com/nginx:latest
[root@docker1 ~]# docker push repo.docker.alexw.com/nginx:latest
The push refers to repository [repo.docker.alexw.com/nginx]
Get "https://repo.docker.alexw.com/v2/": x509: certificate signed by unknown authority
# 放置自签名证书到规定位置
[root@docker1 certs.d]# mkdir repo.docker.alexw.com
[root@docker1 certs.d]# cd repo.docker.alexw.com/
[root@docker1 repo.docker.alexw.com]# pwd
/etc/docker/certs.d/repo.docker.alexw.com
[root@docker1 repo.docker.alexw.com]# cp /root/certs/repo.docker.alexw.com.crt ca.crt
# 再次push
[root@docker1 repo.docker.alexw.com]# docker push repo.docker.alexw.com/nginx:latest
The push refers to repository [repo.docker.alexw.com/nginx]
80115eeb30bc: Pushed
049fd3bdb25d: Pushed
ff1154af28db: Pushed
8477a329ab95: Pushed
7e7121bf193a: Pushed
67a4178b7d47: Pushed
latest: digest: sha256:4c1c50d0ffc614f90b93b07d778028dc765548e823f676fb027f61d281ac380d size: 1570
[root@docker1 repo.docker.alexw.com]# curl -k https://repo.docker.alexw.com/v2/_catalog
{"repositories":["nginx"]}
# 远程访问配置
[root@server2 ~]# vim /etc/docker/daemon.json
{
"registry-mirrors":["https://repo.docker.alexw.com"]
}
-
- 本地Harbor仓库搭建
-
-
- Harbor是由VMware公司开源的企业级的Docker Registry管理项目
-
-
-
- 需要docker和docker-compose
-
-
-
- harbor会自动创建registry容器,所以原先有的需要删除
-
### 安装docker-compose
### https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-linux-x86_64
[root@server1 ~]# mv docker-compose-linux-x86_64-v2.5.0 /usr/bin/docker-compose
[root@server1 ~]# chmod 755 /usr/bin/docker-compose
[root@server1 ~]# docker-compose version
Docker Compose version v2.5.0
### 生成签名文件
## 要确保Harbor读取到的认证文件和docker配置路径的认证文件一致,然后可以分发.crt文件到其他节点
[root@docker1 ~]# yum install -y openssl11-libs-1.1.1k-2.el7.x86_64.rpm openssl11-1.1.1k-2.el7.x86_64.rpm
[root@docker1 ~]# openssl11 req -newkey rsa:4096 -nodes -sha256 -keyout certs/repo.docker.alexw.com.key --addext "subjectAltName=DNS:repo.docker.alexw.com" -x509 -days 365 -out certs/repo.docker.alexw.com.crt
Generating a RSA private key
...................................................................................++++
............................................................................................++++
writing new private key to 'certs/repo.docker.alexw.com.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:shaanxi
Locality Name (eg, city) [Default City]:xi'an
Organization Name (eg, company) [Default Company Ltd]:alexw
Organizational Unit Name (eg, section) []:alexw
Common Name (eg, your name or your server's hostname) []:repo.docker.alexw.com
Email Address []:
### 准备data目录,安装harbor
### https://github.com/vmware/harbor/releases/download/v1.1.2/harbor-online-installer-v1.1.2.tgz
[root@server1 cert]# mkdir /data/harbor -p && cd /data/harbor
[root@server1 harbor]# tar xvf ~/harbor-offline-installer-v2.5.0.tgz
harbor/harbor.v2.5.0.tar.gz
harbor/prepare
harbor/LICENSE
harbor/install.sh
harbor/common.sh
harbor/harbor.yml.tmpl
### 修改配置
[root@server1 harbor]# cp harbor.yml.tmpl harbor.yml
[root@server1 harbor]# vim harbor.yml
hostname: repo.docker.alexw.com # 本机域名
http:
port: 80
https:
port: 443
certificate: /data/cert/alexw.com.crt #证书
private_key: /data/cert/alexw.com.key #证书
harbor_admin_password: Harbor12345 #harbor的初始密码,初始用户admin
database:
password: root123 #数据库的密码
data_volume: /data/harbor/data
metric: #配置监控
enabled: true
port: 9090
path: /metrics
### 安装harbor,提前清除registry容器
[root@server1 harbor]# ./install.sh --with-chartmuseum --with-trivy
测试:
- 镜像加速器
[root@localhost docker]# vim /etc/docker/daemon.json
{
"registry-mirrors":["https://registry.docker-cn.com"]
}
[root@localhost docker]# systemctl daemon-reload
[root@localhost docker]# systemctl restart docker
四、Docker网络
- 容器的IP是不固定的,只要小地址未被占用,IP就会变更为小地址
- 默认三种模式:bridge、host、null
[root@docker1 repo.docker.alexw.com]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242767156ce no veth6ed92c4
[root@docker1 repo.docker.alexw.com]# docker network ls
NETWORK ID NAME DRIVER SCOPE
fcc4452c4694 bridge bridge local ### 默认使用,桥接模式
ce343fd58ec8 host host local ### 与宿主机共享ip
09c63c4e5277 none null local ### 禁用
# docker默认使用的网卡是docker0,和宿主机是桥接模式,网关是172.17.0.1/16,运行的容器默认都在这个网段
[root@docker1 repo.docker.alexw.com]# 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:ae:26:1c brd ff:ff:ff:ff:ff:ff
inet 192.168.147.138/24 brd 192.168.147.255 scope global noprefixroute dynamic ens33
valid_lft 1499sec preferred_lft 1499sec
inet6 fe80::37d4:a5b5:b4b6:19cc/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:76:71:56:ce 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:76ff:fe71:56ce/64 scope link
valid_lft forever preferred_lft forever
67: veth6ed92c4@if66: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether ba:42:31:bf:54:82 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::b842:31ff:febf:5482/64 scope link
valid_lft forever preferred_lft forever
# 与宿主机共享IP模式启动容器
[root@docker1 repo.docker.alexw.com]# docker run -d --network host --name demonginx nginx
6a3b8117dc5e7bf97bb3ac5b2a78120b77f5fb8becf344dc50b2164afa6f39ad
自定义网络
- 三种模式:bridge(自带DNS,容器名作为域名)、overlay(用于集群)、macvlan
[root@docker1 repo.docker.alexw.com]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
桥接模式
- 提供DNS,容器名即域名
# 默认使用的就是桥接模式,如果不指定网段,会自动分配
[root@docker1 repo.docker.alexw.com]# docker network create testnet
6ebd82e16e6a0a54e19cb78c2abba4178582b229516d955804270959691c8a00
# 启动一个nginx容器,使用testnet
[root@docker1 repo.docker.alexw.com]# docker run -d -p 8008:80 --name web1 --network testnet nginx
208132dfb3f9b007802238eb5e5460e58f6a9550f294666edf862e3a4cf35d16
# 启动另一个容器,使用testnet
[root@docker1 repo.docker.alexw.com]# docker run -it --rm --network testnet busybox
/ #
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
75: eth0@if76: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 可以看到,域名正确解析,web1获取到172.18.0.2的地址
/ # ping web1
PING web1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.126 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.089 ms
# 自己指定网段
[root@docker1 repo.docker.alexw.com]# docker network create --subnet 10.0.0.0/24 --gateway 10.0.0.1 newtestnet
d362aefe6a76bb3eed0cac7aacdfb2ff63a66b20c13ef3e984952604fc9ef78f
[root@docker1 repo.docker.alexw.com]# docker run -d -p 8009:80 --name web2 --network newtestnet nginx
e461b738d7dd20fac740ed706e20db983f89befd1e0d2d4071829adb997876ad
[root@docker1 repo.docker.alexw.com]# docker run -it --rm --network newtestnet busybox
/ #
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
82: eth0@if83: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:0a:00:00:03 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.3/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ping web2
PING web2 (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.272 ms
64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.081 ms
配置不同网段网络互联
# web1网段172.18.0.0/16,client网段10.0.0.2/24
[root@server1 ~]# docker network connect testnet client
[root@docker1 repo.docker.alexw.com]# docker run -it --rm --name client --network newtestnet busybox
/ #
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
92: eth0@if93: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.2/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
92: eth0@if93: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.2/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
94: eth1@if95: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.3/16 brd 172.18.255.255 scope global eth1
valid_lft forever preferred_lft forever
/ # ping web1
PING web1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.257 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.109 ms
joined模式
- 容器之间可以使用同一接口接入外部服务
[root@docker1 repo.docker.alexw.com]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
48c8689a36ae nginx "/docker-entrypoint.…" 32 minutes ago Up 32 minutes 0.0.0.0:8001->80/tcp, :::8001->80/tcp web1
36f9d1862f07 registry "/entrypoint.sh /etc…" 2 hours ago Up 2 hours 0.0.0.0:443->443/tcp, :::443->443/tcp, 5000/tcp registry
[root@docker1 repo.docker.alexw.com]# docker run -it --rm --network container:web1 --name server busybox
/ #
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
84: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # netstat -antlp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.11:43100 0.0.0.0:* LISTEN -
tcp 0 0 :::80 :::* LISTEN -
/ #
# 自动做了hosts解析
/ # cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2 48c8689a36ae
容器与外网通信过程
- 出:通过iptables的SNAT实现的
- 入:docker-proxy和SNAT
[root@docker1 repo.docker.alexw.com]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 3 packets, 188 bytes)
pkts bytes target prot opt in out source destination
74 3936 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 2 packets, 104 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 102 packets, 7624 bytes)
pkts bytes target prot opt in out source destination
41 2484 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 103 packets, 7708 bytes)
pkts bytes target prot opt in out source destination
11 586 MASQUERADE all -- * !br-d362aefe6a76 10.0.0.0/24 0.0.0.0/0
0 0 MASQUERADE all -- * !br-6ebd82e16e6a 172.18.0.0/16 0.0.0.0/0
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:443
0 0 MASQUERADE tcp -- * * 172.18.0.2 172.18.0.2 tcp dpt:80
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- br-d362aefe6a76 * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- br-6ebd82e16e6a * 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
50 3000 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 to:172.17.0.2:443
0 0 DNAT tcp -- !br-6ebd82e16e6a * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8001 to:172.18.0.2:80
五、Docker数据卷
对比分层文件系统和数据卷
- docker分层系统性能差、生命周期与容器相同
- docker数据卷,直接mount到宿主机、和宿主机磁盘性能相同、容器删除后依然保留、仅限本地磁盘、不能随容器迁移
docker提供两种卷
- bind mount
使用-v指定挂载,默认权限为rw。指定只读权限ro
[root@server1 website]# docker run -d -p 8001:80 --name web1 -v /opt/website:/usr/share/nginx/html -v /root/test1:/test1:rw -v /root/test2:/test2:ro nginx
097138c0bfc157f5a54baccf70bf1a89998a989ebbf1d06b13dfe18fa18e9969
- docker managed volume
必须指定在/var/lib/docker/volumes中,不需要指定mount源,docker自动创建数据源路径。如果指向容器内已有的目录,原有数据会被复制到volume中,只能挂载目录
[root@server1 website]# docker run -d --name web2 -p 8002:80 -v /usr/share/nginx/html nginx
# 自动创建源挂载目录
[root@server1 website]# ll /var/lib/docker/volumes/8c6efd750bb393900003e3584533c176522042b12dbfa19f107fbb3e2eda1bc0/_data/
total 8
-rw-r--r--. 1 root root 497 Dec 13 07:53 50x.html
-rw-r--r--. 1 root root 615 Dec 13 07:53 index.html
[root@server1 website]# cat index.html
index from rhel7
# 指定挂载目录
[root@server1 website]# docker volume create vol1
vol1
[root@server1 website]# docker run -d -p 8003:80 --name web3 -v vol1:/usr/share/nginx/html nginx
51a0b1537488fb7a0b82ff1f17a63c99b1c1ee149fb4970fc9be5d40bf5ff73b
[root@server1 website]# ll /var/lib/docker/volumes/vol1/_data/
total 8
-rw-r--r--. 1 root root 497 Dec 13 07:53 50x.html
-rw-r--r--. 1 root root 615 Dec 13 07:53 index.html
[root@server1 website]# cat index.html
index from rhel7
# 创建容器,并挂载现有目录
[root@server1 website]# docker create --name datavol1 -v vol1:/root/test1 busybox
5ff8aace31217665882a83f67943d963e8e286be3b8e5db952d37e98e036c3ab
[root@server1 website]# docker run -it --rm --volumes-from datavol1 busybox
/ #
六、Docker安全
概念
- linux内核的命名空间提供的容器隔离
- linux控制组机制对容器资源的控制
- linux内核工作机制带来的操作权限安全
- Docker本身的抗攻击性
容器资源控制
- Linux Cgroups(Linux Control Group),限制一个进程组能够使用的资源上限
- Linux Cgroup给用户暴露出的操作接口是文件系统,以文件或目录的方式暴露在/sys/fs/cgroup路径
- mount -t cgroup
[root@server1 ~]# docker run --help | grep cpu
--cpu-period int Limit CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota
--cpu-rt-period int Limit CPU real-time period in microseconds
--cpu-rt-runtime int Limit CPU real-time runtime in microseconds
-c, --cpu-shares int CPU shares (relative weight)
--cpus decimal Number of CPUs
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
# 指定容器使用cpu的时间总量,需要--cpu-period 和--cpu-quota搭配,默认值是-1表示未设置
[root@server1 ~]# docker run -it --rm --cpu-period 100000 --cpu-quota 20000 busybox
# 配置写入在下面这个路径
[root@server1 ~]# cat /sys/fs/cgroup/cpu/docker/f035979f6c5c8cde99889183833f0166b3c022e619a8ba07b06494b5246ee5dd/cpu.cfs_quota_us
20000
# 设置容器使用cpu的优先级,默认1024
[root@server1 ~]# docker run -it -d --name os1 --cpu-shares 100 busybox
# 指定容器能使用的内存量,--memory(对应文件memory.limit_in_bytes)和--memory-swap(对应文件memory.memsw.limit_in_bytes)配合使用(如果宿主机有swap的话)
[root@server1 ~]# docker run -it --memory 200M --memory-swap 200M busybox
# 限制IO速度,当前仅对direct IO有效
[root@server1 memory]# docker run -it --name os2 --device-write-bps /dev/sda:30MB busybox
/ # dd if=/dev/zero of=bigdata bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (100.0MB) copied, 0.291955 seconds, 342.5MB/s
/ # dd if=/dev/zero of=bigdata bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (100.0MB) copied, 3.337992 seconds, 30.0MB/s
docker安全加固
- lxcfs
[root@server1 ~]# docker run -it -m 256m\
> -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw\
> -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw\
> -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw\
> -v /var/lib/lxcfs/proc/stat:/proc/stat:rw\
> -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw\
> -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw\
> busybox
- –cap-add | --cap-drop | privileged