简介

Docker是什么

Docker是一个在2013年开源的使用go语言编写的PaaS服务。特点是交付速度快、资源消耗低。Docker采用客户端/服务端架构,使用远程API来管理和创建Docker容器。它的三大理念是build、ship、run,使用Namespace及cggroup等来提供容器的资源隔离与安全保障。

Docker的组成

  • Docker主机(Host):物理机或者虚机,用于运行Docker服务进程和容器;
  • Docker服务端(Server):Docker守护进程,运行Docker容器;
  • Docker客户端(Client):客户端使用docker命令或者其他工具调用相应API;
  • Docker仓库(Registroy):保存镜像的仓库,类似git这样的版本控制系统;
  • Docker镜像(Images):镜像可以理解为创建实例使用的模板;
  • Docker容器(Container):容器是从镜像生成对外提供服务的一个或者一组服务。

NameSpace技术

命名空间保证容器之间的运行环境互相隔离,可以使每个进程看起来都拥有自己的隔离的全局系统资源。

  • MNT NameSpace:提供存储隔离能力
  • IPC NameSpace:提供进程间通信隔离能力
  • UTS NameSpace:提供主机名隔离能力
  • PID NameSpace:提供进程隔离能力
  • Net NameSpace:提供网络隔离能力
  • User NameSpace:提供用户隔离能力

Control Groups

容器的本质就是进程,为了让容器中的进程可控,Docke使用Linux cgroups来限制容器能够使用资源的上限,包括CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级配置,以及将进程挂起和恢复。

# 验证CGROUP
[root@vms101 ~]# cat /boot/config-3.10.0-1160.90.1.el7.x86_64 |grep CGROUP
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_SCHED=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=y
CONFIG_NETPRIO_CGROUP=y

# 查看系统cgroups
[root@vms101 ~]# ll /sys/fs/cgroup/
total 0
drwxr-xr-x. 4 root root 0 May 9 03:40 blkio
lrwxrwxrwx. 1 root root 11 May 9 03:40 cpu -> cpu,cpuacct
lrwxrwxrwx. 1 root root 11 May 9 03:40 cpuacct -> cpu,cpuacct
drwxr-xr-x. 4 root root 0 May 9 03:40 cpu,cpuacct
drwxr-xr-x. 2 root root 0 May 9 03:40 cpuset
drwxr-xr-x. 4 root root 0 May 9 03:40 devices
drwxr-xr-x. 2 root root 0 May 9 03:40 freezer
drwxr-xr-x. 2 root root 0 May 9 03:40 hugetlb
drwxr-xr-x. 4 root root 0 May 9 03:40 memory
lrwxrwxrwx. 1 root root 16 May 9 03:40 net_cls -> net_cls,net_prio
drwxr-xr-x. 2 root root 0 May 9 03:40 net_cls,net_prio
lrwxrwxrwx. 1 root root 16 May 9 03:40 net_prio -> net_cls,net_prio
drwxr-xr-x. 2 root root 0 May 9 03:40 perf_event
drwxr-xr-x. 4 root root 0 May 9 03:40 pids
drwxr-xr-x. 4 root root 0 May 9 03:40 systemd

cgroups的具体实现

  • blkio:块设备的IO限制
  • cpu:使用调度程序为任务提供CPU的访问
  • cpu.stat:产生任务的CPU资源报告
  • cpuset:多核CPU的调度
  • memory:设置任务的内存限制以及产生内存资源报告
  • ns:命名空间子系统
  • net_cls:标记每个网络包以供cgroups任务使用

核心技术

容器规范

  • runtime spec
  • image format spec

容器运行时

  • LXC
  • runc
  • rkt

容器管理工具

  • RKT的管理工具是rkt cli
  • Runc的管理工具是Docker engine
  • LXC|LXD的管理工具就是lxc

容器定义工具

  • Docker Image:Docker容器的模板
  • DockerFile:包含N个命令的文本文件,通过定义Dockerfile来创建Docker Image
  • ACI(App Container Image):与DockerImage类似,是CoreOS开发的rkt容器镜像格式

镜像仓库(Registry)

统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库。

  • Image Registry:Docker官方提供的私有仓库部署工具
  • Docker Hub:Docker官方的公共仓库
  • Harbor:VMware提供的带WEB界面自带认证功能的镜像仓库

编排工具

容器编排通常包括容器管理、调度、集群定义和服务发现等功能。

  • Docker Swarm:Docker官方开发的容器编排引擎
  • Kubernetes:Google领导开发的容器编排引擎,其内部项目为Borg,支持Docker和CoreOS

依赖技术

容器网络

Docker自带网络功能的docker network仅支持管理单机容器网络,多主机运行需要使用第三方开源网络插件,例如calico、flannel等。

服务发现

容器的动态扩容特性决定了容器IP会动态变化,需要一种机制自动识别并将用户请求动态转发到新的容器上。k8s自带服务发现功能,需要结合kube-dns服务解析域名。

容器监控

Docker原生命令Docker ps/top/stats可以查看容器运行状态,也可以使用Promeheus等第三方工具监控容器运行状态。

数据管理

容器的在不同Host之间的动态迁移就需要相关数据也要随之迁移,需要使用解决其数据存储和挂载问题。

日志收集

Docker原生日志查看工具是docker logs,但容器内部日志需要通过ELK等专门日志工具进行收集、分析和展示。

容器安装

安装

# 以CentOS7为例,使用华为源
# 设置默认防火墙配置为信任区域
firewall-cmd --set-default-zone=trusted
# 配置软件安装源
wget -O /etc/yum.repos.d/docker-ce.repo https://repo.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+repo.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# 执行部署
yum makecache fast
yum update
yum remove -y docker docker-common docker-selinux docker-engine
yum install -y yum-utils device-mapper-persistent-data lvm2 psmisc net-tools
# 安装指定版本
yum install -y docker-ce
# 配置加速源
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://37y8py0j.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
systemctl daemon-reload
systemctl restart docker
# 启动
systemctl enable --now docker

# 修改内核参数
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

sysctl --system

验证服务

# 查看版本信息
[root@vms101 ~]# docker version
Client: Docker Engine - Community
Version: 23.0.5
API version: 1.42
Go version: go1.19.8
Git commit: bc4487a
Built: Wed Apr 26 16:18:56 2023
OS/Arch: linux/amd64
Context: default

Server: Docker Engine - Community
Engine:
Version: 23.0.5
API version: 1.42 (minimum version 1.12)
Go version: go1.19.8
Git commit: 94d3ad6
Built: Wed Apr 26 16:16:35 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.20
GitCommit: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
runc:
Version: 1.1.5
GitCommit: v1.1.5-0-gf19387a
docker-init:
Version: 0.19.0
GitCommit: de40ad0
# 验证Docker0网卡
[root@vms101 ~]# 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:e6:56:9d:47 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@vms101 ~]# docker info
Client:
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.10.4
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.17.3
Path: /usr/libexec/docker/cli-plugins/docker-compose

Server:
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 1
Server Version: 23.0.5
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 2806fc1057397dbaeefbea0e4e17bddfbd388f38
runc version: v1.1.5-0-gf19387a
init version: de40ad0
Security Options:
seccomp
Profile: builtin
Kernel Version: 3.10.0-1160.90.1.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 3.839GiB
Name: vms101
ID: 589aba66-198e-4805-9ae2-518d17585521
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://37y8py0j.mirror.aliyuncs.com/
Live Restore Enabled: false

服务进程

  • dockerd:被Client直接访问,其父进程为Host的Systemd守护进程
  • docker-proxy:实现容器通信,其父进程为dockerd
  • containerd:被dockerd进程调用以实现与runc交互
  • containerd-shim:真正运行容器的载体,其父进程为containerd
# 查看宿主机进程树
[root@vms101 ~]# pstree -p 1
systemd(1)─┬─NetworkManager(881)─┬─{NetworkManager}(886)
│ └─{NetworkManager}(892)
├─containerd(1191)─┬─{containerd}(1208)
│ ├─{containerd}(1212)
│ ├─{containerd}(1213)
│ ├─{containerd}(1214)
│ ├─{containerd}(1242)
│ ├─{containerd}(1253)
│ ├─{containerd}(1254)
│ └─{containerd}(1285)
├─containerd-shim(2030)─┬─nginx(2051)─┬─nginx(2101)
│ │ └─nginx(2102)
│ ├─{containerd-shim}(2031)
│ ├─{containerd-shim}(2032)
│ ├─{containerd-shim}(2033)
│ ├─{containerd-shim}(2034)
│ ├─{containerd-shim}(2035)
│ ├─{containerd-shim}(2036)
│ ├─{containerd-shim}(2037)
│ ├─{containerd-shim}(2038)
│ ├─{containerd-shim}(2039)
│ └─{containerd-shim}(2040)
├─containerd-shim(2139)─┬─nginx(2159)─┬─nginx(2212)
│ │ └─nginx(2213)
│ ├─{containerd-shim}(2141)
│ ├─{containerd-shim}(2142)
│ ├─{containerd-shim}(2143)
│ ├─{containerd-shim}(2144)
│ ├─{containerd-shim}(2145)
│ ├─{containerd-shim}(2146)
│ ├─{containerd-shim}(2147)
│ ├─{containerd-shim}(2153)
│ ├─{containerd-shim}(2179)
│ ├─{containerd-shim}(2180)
│ └─{containerd-shim}(2181)
├─dockerd(1290)─┬─docker-proxy(2011)─┬─{docker-proxy}(2012)
│ │ ├─{docker-proxy}(2013)
│ │ ├─{docker-proxy}(2014)
│ │ ├─{docker-proxy}(2015)
│ │ └─{docker-proxy}(2016)
│ ├─docker-proxy(2017)─┬─{docker-proxy}(2018)
│ │ ├─{docker-proxy}(2019)
│ │ ├─{docker-proxy}(2020)
│ │ ├─{docker-proxy}(2021)
│ │ └─{docker-proxy}(2022)
│ ├─docker-proxy(2121)─┬─{docker-proxy}(2122)
│ │ ├─{docker-proxy}(2123)
│ │ ├─{docker-proxy}(2124)
│ │ ├─{docker-proxy}(2125)
│ │ └─{docker-proxy}(2126)
│ ├─docker-proxy(2127)─┬─{docker-proxy}(2128)
│ │ ├─{docker-proxy}(2129)
│ │ ├─{docker-proxy}(2130)
│ │ ├─{docker-proxy}(2131)
│ │ └─{docker-proxy}(2132)
│ ├─{dockerd}(1373)
│ ├─{dockerd}(1374)
│ ├─{dockerd}(1375)
│ ├─{dockerd}(1376)
│ ├─{dockerd}(1462)
│ ├─{dockerd}(1463)
│ ├─{dockerd}(1464)
│ └─{dockerd}(1868)

容器的创建与管理

通信流程

  1. dockerd通过grpc和containerd模块通信,dockerd由libcontainerd负责和contaiinerd进行交换,socket文件为:/run/containerd/containerd.sock;
  2. containerd在dockerd启动时被启动,然后containerd启动grpc请求监听,containerd处理grpc请求;
  3. 若是start或者exec容器,containerd拉起一个container-shim,并进行相关操作;
  4. container-shim拉起后,start/exec/create拉起runC进程,通过exit、control文件和containerd通信,通过父子进程关系和SIGCHLD监控容器中的进程状态;
  5. 在整个容器生命周期中,containerd通过epoll监控容器文件,监控容器事件。

镜像管理

Docker镜像包含有启动容器所需要的文件系统及所需要的内容,因此镜像主要用于创建并启动Docker容器。Docker镜像包含多层文件系统,称为UnionFS联合文件系统,它将多层目录挂载到一起,形成一个虚拟文件系统,每一层叫做一层layer,每层文件系统有只读(readonly)、读写(readwrite)和写出(whiteout-able)三种权限,但每层文件系统都是只读的。构建镜像的时候,每个构建的操作都增加一层文件系统,一层层往上叠加,上层的修改会覆盖底层的可见性。

# 搜索镜像
# 按最新版搜索
[root@vms101 ~]# docker search centos
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
centos DEPRECATED; The official build of CentOS. 7575 [OK]
kasmweb/centos-7-desktop CentOS 7 desktop for Kasm Workspaces 36
bitnami/centos-base-buildpack Centos base compilation image 0 [OK]
# 指定版本搜索
[root@vms101 ~]# docker search centos:7.2
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
vikingco/python Python Stack Docker Base Image: Based on cen… 1
alvintz/centos centos:7.2.1511 0 [OK]
morrowind/centos From centos:7.2 0
# 下载镜像
[root@vms101 ~]# docker pull alpine
Using default tag: latest
latest: Pulling from library/alpine
59bf1c3509f3: Pull complete
Digest: sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
# 查看本地镜像
[root@vms101 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
alpine latest c059bfaa849c 17 months ago 5.59MB
centos latest 5d0da3dc9764 20 months ago 231MB
# 镜像导出
[root@vms101 ~]# docker save centos -o /opt/centos.tar.gz
[root@vms101 ~]# ll /opt/centos.tar.gz
-rw-------. 1 root root 238581248 May 9 04:26 /opt/centos.tar.gz
[root@vms101 ~]# tar xvf /opt/centos.tar.gz
079bc5e75545bf45253ab44ce73fbd51d96fa52ee799031e60b65a82e89df662/
079bc5e75545bf45253ab44ce73fbd51d96fa52ee799031e60b65a82e89df662/VERSION
079bc5e75545bf45253ab44ce73fbd51d96fa52ee799031e60b65a82e89df662/json
079bc5e75545bf45253ab44ce73fbd51d96fa52ee799031e60b65a82e89df662/layer.tar
5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6.json
manifest.json
tar: manifest.json: implausibly old time stamp 1970-01-01 08:00:00
repositories
tar: repositories: implausibly old time stamp 1970-01-01 08:00:00
# 镜像删除
[root@vms101 ~]# docker rmi centos
Untagged: centos:latest
Untagged: centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Deleted: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6
Deleted: sha256:74ddd0ec08fa43d09f32636ba91a0a3053b02cb4627c35051aff89f853606b59
# 镜像导入
[root@vms101 ~]# docker load < /opt/centos.tar.gz
74ddd0ec08fa: Loading layer [==================================================>] 238.6MB/238.6MB
Loaded image: centos:latest
[root@vms101 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
alpine latest c059bfaa849c 17 months ago 5.59MB
centos latest 5d0da3dc9764 20 months ago 231MB
# 镜像的重新打标签
[root@vms101 nginx]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sujx/nginx-yum-file v1 97d106d963e7 9 minutes ago 2.42GB
centos latest 5d0da3dc9764 20 months ago 231MB
[root@vms101 nginx]# docker tag centos
centos:7.9.2009 centos:latest centos-nginx:v1
[root@vms101 nginx]# docker tag centos:latest centos8
[root@vms101 nginx]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos8 latest 5d0da3dc9764 20 months ago 231MB
centos latest 5d0da3dc9764 20 months ago 231MB
# 查看镜像的文件层次
[root@vms101 nginx]# docker history centos8
IMAGE CREATED CREATED BY SIZE COMMENT
5d0da3dc9764 20 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 20 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 20 months ago /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0… 231MB

容器管理

# 显示所有容器
[root@vms101 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a36e33a02f0 nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:83->80/tcp, :::83->80/tcp ngingx-3
1353d6b1c4f2 nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:82->80/tcp, :::82->80/tcp ngingx-2
# 从镜像启动一个容器
[root@vms101 ~]# docker run -it centos bash
[root@c82b8168f173 /]#
# 使用crtl+p+q推出容器而不注销
[root@vms101 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c82b8168f173 centos "bash" 18 seconds ago Up 17 seconds eager_nash
6a36e33a02f0 nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:83->80/tcp, :::83->80/tcp ngingx-3
1353d6b1c4f2 nginx "/docker-entrypoint.…" About an hour ago Up About an hour 0.0.0.0:82->80/tcp, :::82->80/tcp ngingx-2
# 进入容器
[root@vms101 ~]# docker exec -it c82b8 bash
[root@c82b8168f173 /]# top
top - 21:28:03 up 1:47, 0 users, load average: 0.00, 0.01, 0.05
Tasks: 3 total, 1 running, 2 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3931.1 total, 2082.2 free, 476.3 used, 1372.5 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 3199.2 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 12036 2088 1572 S 0.0 0.1 0:00.03 bash
21 root 20 0 12036 2088 1572 S 0.0 0.1 0:00.02 bash 35 root 20 0 49112 2164 1520 R 0.0 0.1 0:00.00 top
# 删除正在运行的容器
[root@vms101 ~]# docker rm c82b
Error response from daemon: You cannot remove a running container c82b8168f173d8d4f0365c8d9672e99db68fd25f224a251b8ac31ef54996b5a1. Stop the container before attempting removal or force remove
[root@vms101 ~]# docker rm -f c82b
c82b
# 设定容器别名并指定端口、后台运行
[root@vms101 ~]# docker run -d --name nginx-1 -p 81:80 nginx
b5b0c251e4e7458e1022722d6b19d287caba93b307636c54a60a0a28e7f4e30c
[root@vms101 ~]# docker run -d --name nginx-2 -p 82:80 nginx
[root@vms101 ~]# docker run -d --name nginx-3 -p 83:80 nginx
[root@vms101 ~]# netstat -tlnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:81 0.0.0.0:* LISTEN 3859/docker-proxy
tcp 0 0 0.0.0.0:82 0.0.0.0:* LISTEN 2011/docker-proxy
tcp 0 0 0.0.0.0:83 0.0.0.0:* LISTEN 2121/docker-proxy
tcp6 0 0 :::81 :::* LISTEN 3865/docker-proxy
tcp6 0 0 :::82 :::* LISTEN 2017/docker-proxy
tcp6 0 0 :::83 :::* LISTEN 2127/docker-proxy
# 查看日志
[root@vms101 ~]# docker logs nginx-1
/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/05/08 21:32:14 [notice] 1#1: using the "epoll" event method
2023/05/08 21:32:14 [notice] 1#1: nginx/1.21.5
2023/05/08 21:32:14 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/05/08 21:32:14 [notice] 1#1: OS: Linux 3.10.0-1160.90.1.el7.x86_64
2023/05/08 21:32:14 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/05/08 21:32:14 [notice] 1#1: start worker processes
2023/05/08 21:32:14 [notice] 1#1: start worker process 31
2023/05/08 21:32:14 [notice] 1#1: start worker process 32
172.16.10.1 - - [08/May/2023:21:34:49 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35" "-"
2023/05/08 21:34:49 [error] 31#31: *2 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.16.10.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "172.16.10.101:81", referrer: "http://172.16.10.101:81/"
172.16.10.1 - - [08/May/2023:21:34:49 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://172.16.10.101:81/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.35" "-"
# 查看容器映射端口
[root@vms101 ~]# docker port nginx-1
80/tcp -> 0.0.0.0:81
80/tcp -> [::]:81
# 传递运行命令,以保持容器的运行
[root@vms101 ~]# docker run -d centos /usr/bin/tail -f '/etc/hosts'
d43c0e0a418819c0638fb63831e0e7becfb2d9ceed408721b98e8b3013bfaa3a
[root@vms101 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d43c0e0a4188 centos "/usr/bin/tail -f /e…" 24 seconds ago Up 23 seconds pedantic_mcclintock
# 容器的停止和运行以及重启
[root@vms101 ~]# docker stop nginx-1
nginx-1
[root@vms101 ~]# docker start nginx-1
nginx-1
[root@vms101 ~]# docker restart nginx-1
nginx-1
[root@vms101 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5b0c251e4e7 nginx "/docker-entrypoint.…" 9 minutes ago Up 9 seconds 0.0.0.0:81->80/tcp, :::81->80/tcp nginx-1
# 使用inspect获取容器相关值
# 获取IP地址
[root@vms101 ~]# docker inspect -f "{{.NetworkSettings.IPAddress}}" nginx-1
172.17.0.4
# 获取容器PID
[root@vms101 ~]# docker inspect -f "{{.State.Pid}}" nginx-1
4216
#使用nsenter命令进入容器
[root@vms101 ~]# yum install -y util-linux
[root@vms101 ~]# nsenter -t 4216 -m -u -i -n -p
root@b5b0c251e4e7:/#
# 批量关闭正在运行的容器
[root@vms101 ~]# docker stop $(docker ps -a -q)
d43c0e0a4188
b5b0c251e4e7
6a36e33a02f0
1353d6b1c4f2
# 批量强制删除已退出容器
[root@vms101 ~]# docker rm -f `docker ps -aq -f status=exited`
d43c0e0a4188
b5b0c251e4e7
6a36e33a02f0
1353d6b1c4f2
# 执行容器的DNS地址
[root@vms101 ~]# docker run -it --rm centos bash
[root@a440c4ada42f /]# cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 223.5.5.5
[root@vms101 ~]# docker run -it --rm --dns 114.114.114.114 centos bash
[root@14689e61b122 /]# cat /etc/resolv.conf
nameserver 114.114.114.114
# 配置随Host拉起镜像 --restart=always
[root@vms101 nginx]# docker run -d --restart=always --name AT-nginx -p 8080:80 nginx
2223df5da188178b7f53043f32387e2ad5c6813b63cfb6030a48960e7d340857

镜像与制作

手动制作YUM版Nginx镜像

# 下载CentOS7.9.2009版本镜像
[root@vms101 ~]# docker pull centos:7.9.2009
[root@vms101 ~]# docker run -it centos:7.0.2009 /bin/bash
# 进入容器
[root@76ea6d768009 /]# yum makecache
[root@76ea6d768009 /]# yum install -y wget
[root@76ea6d768009 /]# wget -O /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo
[root@76ea6d768009 /]# yum install -y epel-release
[root@76ea6d768009 /]# sed -i "s/#baseurl/baseurl/g" /etc/yum.repos.d/epel.repo
[root@76ea6d768009 /]# sed -i "s/metalink/#metalink/g" /etc/yum.repos.d/epel.repo
[root@76ea6d768009 /]# sed -i "s@https\?://download.fedoraproject.org/pub@https://repo.huaweicloud.com@g" /etc/yum.repos.d/epel.repo
[root@76ea6d768009 /]# yum makecache
[root@76ea6d768009 /]# yum update -y
[root@76ea6d768009 /]# yum install -y vim wget pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
[root@76ea6d768009 /]# yum install -y nginx
# 修改Nginx配置
[root@76ea6d768009 /]# rm -f /usr/share/nginx/html/index.html
[root@76ea6d768009 /]# echo "Docker YUM Nginx" >> /usr/share/nginx/html/index.html
[root@76ea6d768009 /]# echo "daemon off;" >> /etc/nginx/nginx.conf
# 提交为镜像,-a 作者信息 -m
[root@vms101 ~]# docker commit -a "sujx@live.cn" -m "nginx yum v1" --change="EXPOSE 80 443" 76ea centos-nginx:v1
sha256:10761eaac11cef2e72957c75e922b9d7a29bf481a4723664f9dc7caa54d4f132
# 查看新生成的镜像
[root@vms101 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos-nginx v1 10761eaac11c About a minute ago 1.04GB
nginx latest 605c77e624dd 16 months ago 141MB
alpine latest c059bfaa849c 17 months ago 5.59MB
centos 7.9.2009 eeb6ee3f44bd 20 months ago 204MB
centos latest 5d0da3dc9764 20 months ago 231MB
# 运行新生成的容器
[root@vms101 ~]# docker run -d -p 80:80 --name my-centos-nginx centos-nginx:v1 /usr/sbin/nginx
4df01551e3778be4be619b5a0fe644e404fc92a527622f4bdeb7cad9005278f8
# 测试
[root@vms101 ~]# curl 127.0.0.1
Docker YUM Nginx

DockerFile制作Nginx镜像

# 创建文件目录
[root@vms101 ~]# cd /opt
[root@vms101 opt]# mkdir -pv dockerfile/{web/{nginx,tomcat,apache},system/{centos,ubuntu,redhat}}
mkdir: created directory ‘dockerfile’
mkdir: created directory ‘dockerfile/web’
mkdir: created directory ‘dockerfile/web/nginx’
mkdir: created directory ‘dockerfile/web/tomcat’
mkdir: created directory ‘dockerfile/web/apache’
mkdir: created directory ‘dockerfile/system’
mkdir: created directory ‘dockerfile/system/centos’
mkdir: created directory ‘dockerfile/system/ubuntu’
mkdir: created directory ‘dockerfile/system/redhat’
[root@vms101 opt]# cd dockerfile/web/nginx/
[root@vms101 nginx]# touch ./Dockerfile
[root@vms101 nginx]# cat > Dockerfile<<EOF
#My Dockerfile
FROM centos:7.9.2009
MAINTAINER sujingxuan "sujx@live.cn"
RUN yum makecache && yum install -y wget && rm -f /var/yum.repos.d/* && wget -O /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo &&yum install -y epel-release && sed -i "s/#baseurl/baseurl/g" /etc/yum.repos.d/epel.repo && sed -i "s/metalink/#metalink/g" /etc/yum.repos.d/epel.repo && sed -i "s@https\?://download.fedoraproject.org/pub@https://repo.huaweicloud.com@g" /etc/yum.repos.d/epel.repo &&yum makecache
RUN yum install -y vim wget pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop nginx
RUN rm -f /usr/share/nginx/html/index.html && RUN echo "Docker YUM Nginx" >> /usr/share/nginx/html/index.html
EXPOSE 80 443
CMD ["nginx","-g","daemon off;"]
EOF
[root@vms101 nginx]# docker build -t sujx/nginx-yum-file:v1 /opt/dockerfile/web/nginx
root@vms101 nginx]# docker build -t sujx/nginx-yum-file:v1 ./
[+] Building 160.1s (7/7) FINISHED ………………
[root@vms101 nginx]# docker run -d --name nginx-dfile -p 80:80 sujx/nginx-yum-file:v1
7b1f4629ff4a451d95c0a5284a06633bb6ae4c66a27ffb28433563045bde2a51
[root@vms101 nginx]# curl 127.0.0.1
Docker YUM Nginx

自定义Tomcat镜像

# 基于CentOS 7.9.2009基础镜像构建JDK和Tomcat镜像。
# 下载基础镜像
[root@vms101 ~]# docker pull centos:7.9.2009
# 构建JDK镜像
[root@vms101 ~]# cd /opt/dockerfile/web/jdk
[root@vms101 jdk]# wget https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.rpm
[root@vms101 jdk]# cat ./Dockerfile
# JDK Base Image
FROM centos:7.9.2009
MAINTAINER sujingxuan "sujx@live.cn"

COPY jdk-8u202-linux-x64.rpm /tmp
RUN rpm -Uvh /tmp/jdk-8u202-linux-x64.rpm

ADD profile /etc/profile

ENV export JAVA_HOME=/usr/java/default
ENV export PATH=$PATH:$JAVA_HOME/bin
ENV export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar

RUN rm -f /etc/localtime && ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone && rm -f /tmp/*.rpm

[root@vms101 jdk]# docker build -t centos-jdk:v1 ./
[+] Building 11.0s (9/9) FINISHED
=> [internal] load .dockerignore => => naming to docker.io/library/centos-jdk:v1
# 验证结果
[root@vms101 ~]# docker run -it --rm --name jdk-test centos-jdk:v1 /bin/bash
[root@4115a47a2c49 /]# java -showversion
java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
[root@4115a47a2c49 /]# vi day.java
import java.util.Calendar;

class day {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH) + 1;
int day = cal.get(Calendar.DATE);
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
System.out.println(year + "/" + month + "/" + day + " " + hour + ":" + minute);
}
}
[root@4115a47a2c49 /]# javac day.java
[root@4115a47a2c49 /]# java day
2023/5/10 23:56
# 构建Tomcat Base镜像

# CentOS7 JDK For Tomcat
[root@vms101 ~]# cd /opt/dockerfile/web/tomcat
[root@vms101 tomcat]# wget https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.88/bin/apache-tomcat-8.5.88.tar.gz
[root@vms101 tomcat]# vim Dockerfile
FROM centos-jdk:v1
MAINTAINER sujingxuan "sujx@live.cn"

ADD apache-tomcat-8.5.88.tar.gz /usr/local/src
RUN useradd -M -d /usr/local/src/apache-tomcat-8.5.88 tomcat
RUN chown -R tomcat:tomcat /usr/local/src/apache-tomcat-8.5.88

ENV TOMCAT_MAJOR_VERSION 8
ENV TOMCAT_MINOR_VERSION 8.5.88
ENV export CATALINA_HOME=/usr/local/src/apache-tomcat-8.5.88
ENV APP_DIR $(CATALINA_HOME)/webapps
[root@vms101 tomcat]# docker build -t tomcat-base:v1 .
[root@vms101 tomcat]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat-base v1 38e080bd23d4 3 minutes ago 815MB
centos-jdk v1 ae6b4f8f0c29 48 minutes ago 785MB
# 构建业务镜像
[root@vms101 tomcat-app1]# vim run_tomcat.sh
#!/bin/bash
su - tomcat -c "/usr/local/src/apache-tomcat-8.5.88/bin/startup.sh start"
tail -f /etc/hosts
[root@vms101 tomcat-app1]# mkdir myapp && echo "Tomcat Web Page1">>myapp/index.html
[root@vms101 tomcat-app1]# vim Dockerfile
# Tomcat WEB APPS
FROM tomcat-base:v1
MAINTAINER sujingxuan "sujx@live.cn"

COPY run_tomcat.sh /usr/local/src/apache-tomcat-8.5.88/
COPY myapp/* /usr/local/src/apache-tomcat-8.5.88/webapps/myapp/

RUN chown -R tomcat:tomcat /usr/local/src/apache-tomcat-8.5.88/
CMD ["/usr/local/src/apache-tomcat-8.5.88/run_tomcat.sh"]
EXPOSE 8080 8005
[root@vms101 tomcat-app1]# docker build -t tomcat-app1:v1 .
[root@vms101 ~]# docker run -it -d -p 80:8080 tomcat-app1:v1
# 验证
[root@vms101 ~]# curl http://172.16.10.101/myapp/
Tomcat Web Page1

# 依据上述操作,准备tomcat-app2镜像
[root@vms101 ~]# docker run -it -d -p 81:8080 tomcat-app1:v1
246cdabbb8ed87ede039306870d4c61dddd27c50b3857b53b0d09efd79046f15
[root@vms101 ~]# docker run -it -d -p 82:8080 tomcat-app2:v1
22a0c67911dac716df2aaf4b24b5927bcd30f590e3b858f6d8bac5f329943fc2
[root@vms101 ~]# curl 127.0.0.1:81/myapp/
Tomcat Web Page1
[root@vms101 ~]# curl 127.0.0.1:82/myapp/
Tomcat Web Page2

构建Haproxy镜像

haproxy_status

# 创建Haproxy启动脚本
[root@vms101 ~]# mkdir /opt/dockerfile/haproxy/ && cd /opt/dockerfile/haproxy/ && touch Dockerfile run_haproxy.sh haproxy.cfg
[root@vms101 haproxy]# cat run_haproxy.sh
#!/bin/bash
haproxy -f /etc/haproxy/haproxy.cfg
/bin/bash

# 创建Haproxy配置文件
[root@vms101 haproxy]# cat haproxy.cfg
global
log 127.0.0.1 local2 info
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 256
user haproxy
group haproxy
daemon

defaults
mode http
log global
option httplog
timeout connect 10s
timeout client 30s
timeout server 30s
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:qwe123!!

frontend http-in
bind *:80
default_backend backend_servers
option forwardfor

backend backend_servers
mode http
balance roundrobin
server web1 172.16.10.101:81 check inter 3000 fall 2 rise 5
server web2 172.16.10.101:82 check inter 3000 fall 2 rise 5
# 创建Haproxy镜像
[root@vms101 haproxy]# cat Dockerfile
#Haproxy Base Image
FROM centos:7.9.2009
MAINTAINER sujingxuan "sujx@live.cn"
RUN yum install -y haproxy
RUN mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.org
COPY haproxy.cfg /etc/haproxy/
COPY run_haproxy.sh /usr/bin/
EXPOSE 80 9999
CMD ["/usr/bin/run_haproxy.sh"]

[root@vms101 haproxy]# docker build -t haproxy-base:v1 .
[+] Building 0.1s (10/10) FINISHED
=> => naming to docker.io/library/haproxy-base:v1
# 拉起前端容器
[root@vms101 ~]# docker run -itd --name haproxy -p 80:80 -p 9999:9999 haproxy-base:v1
91dfb0cb8d8fbf1c81b8804819eba4a308c57209da84ba526cb1bf15be1de2e6
[root@vms101 ~]# docker ps
91dfb0cb8d8f haproxy-base:v1 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:9999->9999/tcp, :::9999->9999/tcp haproxy
5ec41ac5f902 tomcat-app1:v1 8005/tcp, 0.0.0.0:81->8080/tcp, :::81->8080/tcp
d903c1419c9b tomcat-app2:v1 8005/tcp, 0.0.0.0:82->8080/tcp, :::82->8080/tcp
# 验证结果
[root@vms101 ~]# curl 127.0.0.1/myapp/
Tomcat Web Page2
[root@vms101 ~]# curl 127.0.0.1/myapp/
Tomcat Web Page1
[root@vms101 ~]# curl 127.0.0.1/myapp/
Tomcat Web Page2
[root@vms101 ~]# curl 127.0.0.1/myapp/
Tomcat Web Page1

数据管理

数据类型

Docker镜像是分层设计,底层只读,通过镜像添加可读写文件系统,用户写入的数据则保存在此层中。

容器的数据分层目录:

  • LowerDir: image 镜像层,即镜像本身,只读
  • UpperDir: 容器的上层,可读写 ,容器变化的数据存放在此处
  • MergedDir: 容器的文件系统,使用Union FS(联合文件系统)将lowerdir 和 upperdir 合并完成后给容器使用,最终呈现给用户的统一视图
  • WorkDir: 容器在宿主机的工作目录,挂载后内容会被清空,且在使用过程中其内容用户不可见
# 拉起一个容器
[root@vms101 ~]# docker run -it -d centos:7.9.2009 /bin/bash
c8dcc79d12a987f4e37c4e9747f37bfe9b4c9ae7eb3a41212ae38b58a0fc0ff4
# 查看容器配置信息
[root@vms101 ~]# docker inspect c8dcc
……
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351-init/diff:/var/lib/docker/overlay2/e8b3f1e50e7ff6272e00ddf3aba286ea0729d65b54c57542970fc180fd350bc3/diff",
"MergedDir": "/var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351/merged",
"UpperDir": "/var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351/diff",
"WorkDir": "/var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351/work"
},
"Name": "overlay2"
},
"Mounts": [],
……
# 在容器中创建文件
[root@vms101 ~]# docker exec -it c8dcc /bin/bash
[root@c8dcc79d12a9 /]# dd if=/dev/zero of=file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.276637 s, 379 MB/s
[root@c8dcc79d12a9 /]# md5sum file
2f282b84e7e608d5852449ed940bfc51 file
[root@c8dcc79d12a9 /]# cp anaconda-post.log /opt/anaconda-post.log
[root@c8dcc79d12a9 /]# exit
exit
# 在Host中查看容器创建的文件
[root@vms101 ~]# tree /var/lib/docker/overlay2/c
c18937983445d3e2d6c11c5bb3ce20a336f9024111c529bd7a99008c27bcf096/ c595c60cf63d162ae9493e112498b941cf8d40a6b7f3bdeb73fa39609383c1e4/ cxn3dw459jii5d9r5iseys6zx/
[root@vms101 ~]# tree /var/lib/docker/overlay2/l
l/ lmv5guk13yscu2hburzkmzyl7/ lwp6qtbel95861tstj3q5tqu5/
[root@vms101 ~]# tree /var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351/diff/
/var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351/diff/
├── file
├── opt
│   └── anaconda-post.log
└── root
2 directories, 2 files
[root@vms101 ~]# md5sum file
md5sum: file: No such file or directory
[root@vms101 ~]# md5sum /var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351/diff/file
2f282b84e7e608d5852449ed940bfc51 /var/lib/docker/overlay2/1e520f13bb5e4cc2ba6776c164c59777f35d00ed7a489e061deeec140293c351/diff/file
# 从宿主机复制文件到容器
[root@vms101 ~]# docker cp testapp/index.html 4d7d:/data

数据卷的特点:

  • 数据卷是目录或者文件,并且可以在多个容器之间共享
  • 对数据卷的更改在所有容器内会立即更新
  • 数据卷的数据可以持久保存,即使删除使用该容器卷的容器也不影响
  • 在容器里面写入数据不会影响镜像本身

数据卷使用场景:

  • 日志输出
  • 静态页面
  • 应用配置文件
  • 多容器间目录或文件共享
# 挂载随机目录,Host会自动创建一个随机名称的volume
[root@vms101 ~]# docker run -d --name files -v /data centos:7.9.2009
4d7d7b6ebee8207a9b24964a76224c4be2853fbda9797d63dadfae5a0d89b374
[root@vms101 ~]# docker inspect 4d7d |grep -A5 Mounts
"Mounts": [
{
"Type": "volume",
"Name": "83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba",
"Source": "/var/lib/docker/volumes/83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba/_data",
"Destination": "/data",
# 查看数据卷
[root@vms101 ~]# docker volume ls
DRIVER VOLUME NAME
local 83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba
# 创建数据卷
[root@vms101 ~]# docker volume create httpd-vol
httpd-vol
# 查看数据卷
[root@vms101 ~]# docker volume ls
DRIVER VOLUME NAME
local 83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba
local httpd-vol
# 数据卷的信息
[root@vms101 ~]# docker volume inspect httpd-vol
[
{
"CreatedAt": "2023-05-11T23:47:10+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/httpd-vol/_data",
"Name": "httpd-vol",
"Options": null,
"Scope": "local"
}
]
[root@vms101 ~]# docker volume inspect 83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba
[
{
"CreatedAt": "2023-05-11T23:28:03+08:00",
"Driver": "local",
"Labels": {
"com.docker.volume.anonymous": ""
},
"Mountpoint": "/var/lib/docker/volumes/83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba/_data",
"Name": "83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba",
"Options": null,
"Scope": "local"
}
]
# 清理卷
[root@vms101 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d7d7b6ebee8 centos:7.9.2009 "/bin/bash" 44 minutes ago Exited (0) 44 minutes ago files
[root@vms101 ~]# docker rm -f 4d7d
4d7d
[root@vms101 ~]# docker volume rm 83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba -f
83c5ae40340c360db9cf11c79f7ccd363a981b18a2e664c22b1d9105cac370ba

绑定挂载

# 创建访问文件
[root@vms101 ~]# mkdir testapp
[root@vms101 ~]# echo "<p><h1>Test APP Page.</h1></p>" > testapp/index.html
[root@vms101 ~]# docker pull httpd
Using default tag: latest
latest: Pulling from library/httpd
a2abf6c4d29d: Already exists
dcc4698797c8: Pull complete
41c22baa66ec: Pull complete
67283bbdd4a0: Pull complete
d982c879c57e: Pull complete
Digest: sha256:0954cc1af252d824860b2c5dc0a10720af2b7a3d3435581ca788dff8480c7b32
Status: Downloaded newer image for httpd:latest
docker.io/library/httpd:latest
# 使用-v参数将目标目录挂载给容器
[root@vms101 ~]# docker run -d --name web -v /root/testapp/:/usr/local/apache2/htdocs/ -p 80:80 httpd
[root@vms101 ~]# curl 127.0.0.1
<p><h1>Test APP Page.</h1></p>
# 删除容器,数据仍然保留
[root@vms101 ~]# docker rm -f 538
538
[root@vms101 ~]# ll testapp/
total 4
-rw-r--r--. 1 root root 51 May 11 23:10 index.html

容器管理卷

数据卷容器可以让数据在多个容器之间共享,需要先创建一个后台运行的容器作为Server用于提供数据存储服务,其他使用此卷的容器作为Client。

# 创建数据存储容器
[root@vms101 ~]# docker run --name data -it -v /data --rm busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
5cc84ad355aa: Pull complete
Digest: sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
Status: Downloaded newer image for busybox:latest
/ #
# 新开一个终端来查看容器属性
[root@vms101 ~]# docker inspect -f {{.Mounts}} data
[{volume dd641a30fbca54f88a6c8e7057e79a5af057cb3e6120b8d521bc3f52d6b743c7 /var/lib/docker/volumes/dd641a30fbca54f88a6c8e7057e79a5af057cb3e6120b8d521bc3f52d6b743c7/_data /data local true }]
# 复制文件到存储容器
[root@vms101 ~]# docker cp testapp/index.html data:/data
Successfully copied 2.05kB to data:/data
[root@vms101 ~]# docker exec data ls /data/testapp
index.html
# 创建客户端容器,指定卷来自于上述的data容器
[root@vms101 ~]# docker run --name client --volumes-from data -it --rm busybox
/ # ls
bin data dev etc home proc root sys tmp usr var
/ # ls /data
testapp
/ # ls /data/testapp/
index.html

# 已关闭存储容器可以再创建客户端容器,已删除存储容器则不能再创建客户端容器,但已经存在的客户端容器不受影响,本质是卷的自动挂载。
# 自动删除容器卷
docker rm -v -f 容器ID

网络部分

Docker服务安装完成之后,默认在宿主机会生成一个名称为docker0的网桥。Docker0是一个二层的网络设备,通过网桥可以将Linux支持的不同端口连接起来,其IP地址为172.17.0.1/16,并生成三种类型的网络:

[root@vms101 ~]# ip a
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:5e:4e:37:81 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:5eff:fe4e:3781/64 scope link
valid_lft forever preferred_lft forever
[root@vms101 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
4645c608490f bridge bridge local
d24bbf5a7ca6 host host local
bbc3fc5e53b4 none null local
# 拉起一个容器之后的网络
[root@vms101 ~]# docker run -d --name web -p 8080:80 nginx
[root@vms101 ~]# ip a
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:16:d2:ae:dc 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:16ff:fed2:aedc/64 scope link
valid_lft forever preferred_lft forever
5: veth2344e4d@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether fe:a1:6c:51:73:87 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::fca1:6cff:fe51:7387/64 scope link
valid_lft forever preferred_lft forever
[root@vms101 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024216d2aedc no veth2344e4d
[root@vms101 ~]# docker run -d --name web1 -p 81:80 nginx
ea153bf7bf6a95f58e46d902d0113c1ce21a1fd1cd8e7004cfdac3e6385523c0
[root@vms101 ~]# docker run -d --name web2 -p 82:80 nginx
096113318c74e3a109451c938fd52f3f1dd48ba146760ce2f8c23de017feb390
[root@vms101 ~]# docker inspect -f {{.NetworkSettings.IPAddress}} web1
172.17.0.3
[root@vms101 ~]# docker inspect -f {{.NetworkSettings.IPAddress}} web2
172.17.0.4

每次新建容器,宿主机就会多一个虚拟网卡,和容器的网卡组成一个网卡,比如veth2344e4d@if4,而在容器内的网卡名为if4。容器会自动获取一个172.17.0.0、16的网段随机地址,默认从172.17.0.2开始。容器获取的地址并不固定,每次重启容器,可能会发生地址变化。该网络设备类型为veth pair,是种成对出现的虚拟网络设备,用于解决网络命名空间之间的隔离。

[root@5926763045b4 /]# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.094 ms
--- 172.17.0.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.094/0.094/0.094/0.000 ms
[root@5926763045b4 /]# ping 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.090 ms
--- 172.17.0.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.070/0.080/0.090/0.010 ms

修改网桥的网络配置

  1. 通过配置Docker的daemon.json来修改

    [root@vms101 ~]# cat /etc/docker/daemon.json 
    {
    "bip": "192.168.100.1/24"
    "registry-mirrors": ["https://37y8py0j.mirror.aliyuncs.com"]
    }
    [root@vms101 ~]# systemctl daemon-reload
    [root@vms101 ~]# systemctl restart docker
    [root@vms101 ~]# ip a
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:16:d2:ae:dc brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 brd 192.168.100.255 scope global docker0
    valid_lft forever preferred_lft forever
    inet6 fe80::42:16ff:fed2:aedc/64 scope link
    valid_lft forever preferred_lft forever
  2. 修改docker服务的配置文件

    [root@vms101 ~]# vim /etc/systemd/system/multi-user.target.wants/docker.service 
    [Service]
    Type=notify
    ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=192.168.100.2/24

    [root@vms101 ~]# systemctl daemon-reload
    [root@vms101 ~]# systemctl restart docker
    [root@vms101 ~]# ip a
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:16:d2:ae:dc brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.2/24 brd 192.168.100.255 scope global docker0
    valid_lft forever preferred_lft forever
    inet6 fe80::42:16ff:fed2:aedc/64 scope link
    valid_lft forever preferred_lft forever

修改默认网桥

[root@vms101 ~]# yum install -y bridge-utils
Package bridge-utils-1.5-9.el7.x86_64 already installed and latest version
Nothing to do
[root@vms101 ~]# brctl addbr br0
[root@vms101 ~]# ip a a 192.168.100.1/24 dev br0
[root@vms101 ~]# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.000000000000 no
docker0 8000.024216d2aedc no
[root@vms101 ~]# ip a
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:16:d2:ae:dc 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:16ff:fed2:aedc/64 scope link
valid_lft forever preferred_lft forever
14: br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether e2:73:fe:78:07:72 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.1/24 scope global br0
valid_lft forever preferred_lft forever
# 修改docker配置文件
[root@vms101 ~]# vim /etc/systemd/system/multi-user.target.wants/docker.service
[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -b br0
[root@vms101 ~]# systemctl daemon-reload
[root@vms101 ~]# systemctl restart docker
[root@vms101 ~]# docker run --rm centos:7.9.2009 hostname -i
192.168.100.2

容器间网络连接

[root@vms101 ~]# docker run -d -it --name web0 -p 80:80 nginx 
54cca62ffbe9fc59f4e7474d0a481136cdbfca68eb677e892c9b98673bc4842d
[root@vms101 ~]# docker run -d -it --name web1 -p 81:80 --link web0 nginx
824595bdb5e4991a506f5b3cb87e4fe88c08696df1be0ab4988c50b89be53bae
[root@vms101 ~]# docker exec -it web1 cat /etc/hosts
172.17.0.2 web0 54cca62ffbe9
172.17.0.3 824595bdb5e4
[root@vms101 ~]# docker run -d -it --name web2 -p 82:80 --link web0 --link web1 nginx
51a303ad5da9476dd1b878064ff927f3fd49511e32b27c10785799d2ecc82a60
[root@vms101 ~]# docker exec -it web2 cat /etc/hosts
172.17.0.2 web0 54cca62ffbe9
172.17.0.3 web1 824595bdb5e4
172.17.0.4 51a303ad5da9
[root@vms101 ~]# docker run -d -it --name web3 -p 83:80 --link web0 --link web1 --link web2 centos:7.9.2009
277807e81bb92a66e1696af982467f66dda719b6e4a3ae2e0499aeabdcba16b5
[root@vms101 ~]# docker exec -it web3 cat /etc/hosts
172.17.0.2 web0 54cca62ffbe9
172.17.0.3 web1 824595bdb5e4
172.17.0.4 web2 51a303ad5da9
172.17.0.5 277807e81bb9
[root@vms101 ~]# docker exec -it web3 /bin/bash
[root@277807e81bb9 /]# ping web0
PING web0 (172.17.0.2) 56(84) bytes of data.
64 bytes from web0 (172.17.0.2): icmp_seq=1 ttl=64 time=0.105 ms
--- web0 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.060/0.082/0.105/0.024 ms
[root@277807e81bb9 /]# ping web2
PING web2 (172.17.0.4) 56(84) bytes of data.
64 bytes from web2 (172.17.0.4): icmp_seq=1 ttl=64 time=0.176 ms
--- web2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.061/0.118/0.176/0.058 ms

网络模式

[root@vms101 ~]# docker run --network 
bridge container: host ipvlan macvlan none null overlay

Docker容器一共有7种网络模式:

  1. bridge模式:默认模式,为每个容器创建自己的网络信息,并将容器连接到一个虚拟网桥与外界通信通过SNAT访问外网,也使用DNAT让容器被外部访问;
    1. 网络资源隔离
    2. 无需手动配置
    3. 可访问外网
    4. 外部主机无法直接访问容器,需要配置DNAT
    5. 性能较低
    6. 端口管理繁琐
  2. Host模式:容器直接使用宿主机Host的网卡和IP地址,网络性能最高,但各个容器内使用端口不能相同,适用于端口固定的模式,各个容器网络无隔离
  3. container模式:与已有容器共享一个网络,与宿主机网络隔离,适合频繁的容器间网络通信,容器进程通过lo网卡进行通信
  4. ipvlan模式:容器使用基于IP的VLAN模式
  5. macvlan模式:容器使用基于Mac的VLAN模式
  6. none/null模式:容器不会进行任何网络配置,无法与外界通信
  7. overlay模式:基于多宿主机和多个容器之间构建分布式的加密网络

配置非HTTPS镜像库

# 下载仓库镜像
[root@vms101 ~]# docker pull registry
# 配置docker服务,使用http而不是默认的https
[root@vms101 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://37y8py0j.mirror.aliyuncs.com"],
"insecure-registries": ["172.16.10.101:5000"]
}
[root@vms101 ~]# systemctl daemon-reload
[root@vms101 ~]# systemctl restart docker

# 配置客户端
[root@vms100 ~]# docker pull hello-world
[root@vms100 ~]# docker tag hello-world:latest 172.16.10.101:5000/cka/helloworld:v1
[root@vms100 ~]# docker push 172.16.10.101:5000/cka/helloworld:v1
The push refers to repository [172.16.10.101:5000/cka/helloworld]
e07ee1baac5f: Pushed
v1: digest: sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 size: 525
# 编写查看registry已有镜像
[root@vms100 ~]# cat list_img.sh
#!/bin/bash
file=$(mktemp)
curl -s $1:5000/v2/_catalog | jq | egrep -v '\{|\}|\[|]' | awk -F\" '{print $2}' > $file
while read aa ; do
tag=($(curl -s $1:5000/v2/$aa/tags/list | jq | egrep -v '\{|\}|\[|]|name' | awk -F\" '{print $2}'))
for i in ${tag[*]} ; do
echo $1:5000/${aa}:$i
done
done < $file
rm -rf $file
[root@vms100 ~]# chmod +x list_img.sh
[root@vms100 ~]# ./list_img.sh 172.16.10.101
172.16.10.101:5000/cka/centos7:v1
172.16.10.101:5000/cka/helloworld:v1
172.16.10.101:5000/rhce8/mysql:v1
172.16.10.101:5000/rhce8/wordpress:v1

单机编排Compose

Docker-compose是容器的一种单机编排工具,用以解决容器的依赖关系,替代docker命令对容器进行创建、启动、停止等手工操作。