目录
  1. 1. docker介绍
    1. 1.1. 什么是docker
      1. 1.1.1. 容器技术
      2. 1.1.2. 使用最为广泛的开源容器引擎
      3. 1.1.3. 容器是一种操作系统级别的虚拟化技术
      4. 1.1.4. 依赖于Linux内核特性 Namespace & Cgroups
      5. 1.1.5. docker能给我们带来什么
      6. 1.1.6. docker使用场景
  2. 2. Linux容器技术VS虚拟机
  3. 3. Docker的基本组成
    1. 3.1. 架构
    2. 3.2. Docker image 镜像
    3. 3.3. Docker Container 容器
    4. 3.4. Docker Registry 仓库
    5. 3.5. 总结
  4. 4. Docker容器相关技术简介
    1. 4.1. Docker依赖的Linux内核特性
    2. 4.2. Docker容器的能力
  5. 5. Docker的安装和配置
    1. 5.1. 配置docker源
    2. 5.2. 安装docker
    3. 5.3. 启动docker服务
    4. 5.4. 4.4配置阿里云镜像加速
  6. 6. Docker的基本操作
    1. 6.1. 启动容器
      1. 6.1.1. 最基本的容器运行
      2. 6.1.2. 交互式启动容器
    2. 6.2. 查看运行的容器
    3. 6.3. 查看详细的容器信息
    4. 6.4. 自定义容器的名字
    5. 6.5. 重新启动已经停止的容器
    6. 6.6. 删除已经停止的容器
  7. 7. Docker守护式容器
    1. 7.1. 什么是守护式容器?
    2. 7.2. 以守护形式运行容器
    3. 7.3. 启动守护式容器
    4. 7.4. 如何查看容器内部运行的情况呢?
    5. 7.5. 查看容器内部的进程
    6. 7.6. 在已经运行的容器启动新的进程
    7. 7.7. 停止守护式容器
  8. 8. 容器中部署静态网站
    1. 8.1. 启动Ubuntu容器
    2. 8.2. 配置NGINX
    3. 8.3. 浏览器查看
      1. 8.3.1. 先查看端口映射
      2. 8.3.2. 访问测试
      3. 8.3.3. 浏览器访问
  9. 9. 端口映射的方式
    1. 9.1. 将容器所有公开的端口发布到宿主机随机端口
    2. 9.2. 指定映射容器的那些端口
      1. 9.2.1. 只指定容器的端口
      2. 9.2.2. 指定宿主机和容器的端口
      3. 9.2.3. 指定IP地址和宿主机、容器的端口
      4. 9.2.4. 指定IP地址和容器的端口
      5. 9.2.5. 查看端口映射情况
  10. 10. 查看和删除镜像
    1. 10.1. 镜像存放的位置
    2. 10.2. 列出镜像
    3. 10.3. 查看镜像的详细内容
    4. 10.4. 删除镜像
  11. 11. 获取和推送镜像
    1. 11.1. 搜索镜像
    2. 11.2. 拉取镜像
    3. 11.3. 推送镜像
      1. 11.3.1. 首先去docker hub注册账号
  12. 12. 构建镜像
    1. 12.1. 什么是构建镜像?
    2. 12.2. 两种构建镜像的方式
      1. 12.2.1. 通过容器构建
    3. 12.3. 通过Dockerfile构建镜像
      1. 12.3.1. 什么是dockerfile?
      2. 12.3.2. dockerfile的基本结构
      3. 12.3.3. dockerfile文件说明
      4. 12.3.4. 通过dockerfile构建nginx
  13. 13. Docker远程连接
    1. 13.1. docker的c/s模式
    2. 13.2. 修改docker的启动脚本
    3. 13.3. 重启docker
    4. 13.4. 远程连接测试
      1. 13.4.1. 浏览器测试
      2. 13.4.2. 使用另一台机器测试
  14. 14. Docker的基础网络类型
    1. 14.1. docker的四种网络类型
    2. 14.2. Bridge桥接模式
      1. 14.2.1. 启动两个容器
      2. 14.2.2. 容器间能互相ping通
    3. 14.3. Host网络模式
      1. 14.3.1. 使用host网络模式启动容器
    4. 14.4. Container网络模式
    5. 14.5. None网络模式
  15. 15. Docker的数据卷
    1. 15.1. 什么是数据卷?
    2. 15.2. 关于UFS文件系统
    3. 15.3. 数据卷的设计目的
    4. 15.4. 为容器添加数据卷
    5. 15.5. 数据卷的权限设置
  16. 16. Docker的数据卷容器
    1. 16.1. 制作数据卷容器
    2. 16.2. 启动数据卷容器
    3. 16.3. 容器连接数据卷容器
  17. 17. 数据卷的备份和还原
    1. 17.1. 数据卷备份操作原理图
    2. 17.2. 数据卷还原
容器化技术--Docker

docker介绍

什么是docker

容器技术

想要了解docker,首先要知道什么是容器。最早的容器技术来自于BSD的jail技术(jail一词是监狱的意思,这个技术的隔离思想来源于监狱的启发),目的就是为了实现进程隔离,使得一个进程被攻陷后不会影响到其他进程,这是出于安全的目的。

使用最为广泛的开源容器引擎

在近几年来,docker是一个非常火的名词。事实上docker只是众多容器引擎其中一款优秀的容器引擎,但是它却几乎成为了容器的代名词。许多业外人士觉得docker就是容器,这里大家要明白,docker只是属于容器技术的一种

容器是一种操作系统级别的虚拟化技术

使用docker创建的容器,以特殊进程的方式在宿主机上运行,运行一个容器就像运行一个进程一样,宿主机上可以运行多个容器,容器间是互相隔离的

依赖于Linux内核特性 Namespace & Cgroups

容器运行的是一个隔离的环境,也可以理解类似于一个沙盒,使用Namespace进行资源的隔离,使用Cgroups进行资源的控制

docker能给我们带来什么

  1. 提供简单轻量的建模方式,非常容易上手,运行速度非常快
  2. 使开发和运维的职责分离,开发只需要关心容器中的程序,运维只需要管理容器
  3. 快速高效的开发生命周期,开发环境和生产环境一致,避免了额外的调试有效缩短上线时间
  4. 鼓励使用面向服务的架构,docker推荐单个容器只运行一个应用程序,使分布式扩展和调试变得简单

docker使用场景

  1. 使用docker容器开发、测试、部署服务
  2. 创建隔离的运行环境
  3. 搭建测试环境
  4. 构建多用户的平台即服务基层设施
  5. 提供软件即服务应用程序
  6. 高性能、超大规模的宿主机部署

Linux容器技术VS虚拟机

大家可以显而易见的看到,使用虚拟机部署应用,不但包含应用和应用依赖的库文件,还包含完整的操作系统,原本可能只需要几十M的应用,却需要动辄几个G的操作系统来支撑。而再看容器的这个图,部署应用只需要应用和应用依赖的库文件,这样资源占用大大减少。另外,虚拟机还需要虚拟硬件,对CPU和内存的损耗非常大。所以同样配置的服务器,使用容器技术要比使用虚拟机,能够提供更多的服务能力,服更多的用户。

虽然容器技术在最近几年才火起来,但容器技术却不是一个新兴的技术。那为什么直到docker的出现,容器技术才真正被大家关注起来呢?因为容器技术本身的复杂性,而且依赖于Linux内核的特性,不易于安装,也不容易管理和实现自动化。然而docker就是为了改变这一切而出现的,docker的出现也让容器技术产生了革命性的改变。

Docker的基本组成

架构

Docker是基于C/S架构的程序,docker的客户端向服务端(也称守护进程)发出请求,守护进程执行的结果会返回到客户端。客户端和守护进程的通信,可以是在本地,也可以通过远程的方式进行。

Docker image 镜像

容器的基石,包含了容器启动的一切条件,容器基于镜像去启动

镜像是层叠的只读文件系统,底层是bootfs引导文件系统,rootfs文件系统永远是只读状态(保证镜像无论启动多少个容器,或者容器被如何修改,都不会改变镜像,使镜像和容器分离)。一个镜像可以放到一个镜像的顶部,最下面的镜像称为基础镜像,就是图中的Ubuntu层。这里利用了COW(copy on write)技术,即从一个镜像启动一个容器实例,这个镜像是以只读形式挂载的,即不允许任何修改操作。当在容器实例中修改一个文件时,会首先从镜像里把这个文件拷贝到可写层,然后执行更新操作。

Docker Container 容器

通过镜像启动

守护进程执行命令就是在容器中执行

应用部署在容器中

在启动容器时,会在镜像的最上层创建一个读写层,在加上下面的只读层,从而构成一个容器

Docker Registry 仓库

仓库里面保存着用户构建的镜像

分为公有仓库(docker公司的仓库)和私有仓库(公司内部使用)

总结

Docker 客户端发送命令给守护进程,守护进程去仓库寻找镜像,如果仓库存在相应镜像,就会通过镜像去启动容器执行相应的操作,如果仓库不存在相应的镜像,就会先把镜像pull到本地镜像仓库。对容器做修改,不会改变镜像的内容。修改后的容器,可以进行提交成为一个新的镜像,它是基于上一个镜像的修改得到的,那上一个镜像就是它的父镜像,镜像的关系可以是层叠的。仓库的作用是保存镜像同时对镜像进行分类。容器相当于一个独立的系统,进入一个基于centos镜像启动的容器就类似进入一个Linux系统,它拥有自己的进程、文件系统、网络等,但却没有自己的内核,通过调用宿主机的内核进行工作。

Docker容器相关技术简介

Docker依赖的Linux内核特性

Namespaces 命令空间

在编程语言中,一般指定是封装代码,实现代码隔离

在操作系统中,是指系统资源的隔离,例如进程、网络、文件系统等…这也是容器所依赖的Linux特性,一个容器中的进程,可以感知容器内其他进程的变化,而对其他容器内的进程一无所知,这就使容器产生一种错觉,仿佛自己置身于独立的操作系统中。

  1. PID—进程隔离
  2. NET—管理网络接口
  3. IPC—管理跨进程通信的访问
  4. MNT—管理挂载点
  5. UTS—隔离内核和版本标识

Control Groups 控制组

  1. 用来分配资源
    1. 资源限制
    2. 优先级设定
    3. 资源计量
    4. 资源控制
  2. 来源于Google
  3. Linux kernel 2.6.24@2007
  4. 为了容器而生,没有Cgroups技术就没有今天的容器技术

Docker容器的能力

  1. 文件系统隔离:每个容器都有自己的root文件系统
  2. 进程隔离:每个容器都运行在自己的进程环境中
  3. 网络隔离:容器间的虚拟网络接口和IP地址都是分开的
  4. 资源隔离和分组:使用cgroup将CPU和内存等资源独立分配给每一个容器

Docker的安装和配置

配置docker源

1
2
3
curl  http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

安装docker

1
2
3
4
[root@docker ~]# yum install -y yum-utils device-mapper-persistent-data lvm2		#依赖包
[root@docker ~]# yum install -y --setopt=obsoletes=0 \
> docker-ce-17.03.2.ce-1.el7.centos.x86_64 \ #主程序是这个包
> docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch

启动docker服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
[root@docker ~]# systemctl daemon-reload	#重新加载systemd程序的配置文件,docker的启动脚本在/usr/lib/systemd/system/docker.service
[root@docker ~]# systemctl restart docker
[root@docker ~]# docker version #能看到server的信息说明启动成功
Client:
Version: 17.03.2-ce
API version: 1.27
Go version: go1.7.5
Git commit: f5ec1e2
Built: Tue Jun 27 02:21:36 2017
OS/Arch: linux/amd64

Server:
Version: 17.03.2-ce
API version: 1.27 (minimum version 1.12)
Go version: go1.7.5
Git commit: f5ec1e2
Built: Tue Jun 27 02:21:36 2017
OS/Arch: linux/amd64
Experimental: false
[root@docker system]# docker info #能看到信息说明启动成功
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 17.03.2-ce
Storage Driver: overlay
Backing Filesystem: extfs
Supports d_type: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc
runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe
init version: 949e6fa
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-957.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 972.6 MiB
Name: docker
ID: 7C2X:HUGL:C67Z:ULWH:3722:BFJM:Q2C3:M4SB:MERP:JNPC:XVZU:V3KB
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
[root@docker system]#

4.4配置阿里云镜像加速

1
2
3
4
5
[root@docker ~]# cat /etc/docker/daemon.json	#不配置国内的docker源,下载速度非常慢
{
"registry-mirrors": ["https://265wemgl.mirror.aliyuncs.com"]
}
[root@docker ~]#

Docker的基本操作

启动容器

最基本的容器运行

1
2
3
4
5
6
[root@docker ~]# docker run ubuntu cat /etc/lsb-release		#启动一个Ubuntu的容器执行一条命令后退出容器,可以使用镜像名或者镜像ID启动
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.2 LTS"
[root@docker ~]#

交互式启动容器

1
2
3
4
5
6
7
8
9
[root@docker ~]# docker container run -it ubuntu /bin/bash
root@febf164ed233:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 01:23 ? 00:00:00 /bin/bash
root 9 1 0 01:23 ? 00:00:00 ps -ef
root@febf164ed233:/#
-i 为容器始终打开标准输入
-t 为容器分配一个伪tty终端
-/bin/bash 启动一个bash

查看运行的容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@docker ~]# docker ps -a	#不加-a参数只会显示正在运行中的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
67481376c1db ubuntu "/bin/bash" 11 seconds ago Exited (0) 8 seconds ago unruffled_mahavira
a0de49b1f37b ubuntu "cat /etc/lsb-release" 19 seconds ago Exited (0) 18 seconds ago sleepy_wozniak
[root@docker ~]#

[root@docker ~]# docker container ls -a #docker新版本查看方法
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
67481376c1db ubuntu "/bin/bash" 2 minutes ago Exited (0) 2 minutes ago unruffled_mahavira
a0de49b1f37b ubuntu "cat /etc/lsb-release" 2 minutes ago Exited (0) 2 minutes ago sleepy_wozniak
[root@docker ~]#

[root@docker ~]# docker container ls -a -q #加-q参数会只显示容器的ID
67481376c1db
a0de49b1f37b
[root@docker ~]#

查看详细的容器信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
[root@docker ~]# docker inspect 67481376c1db		#可以是容器的名字可以是容器的ID
[
{
"Id": "67481376c1dbd16f2cdb45f95dbc89758df1ae267289f96aca286242dab36578",
"Created": "2019-07-31T03:15:25.938873941Z",
"Path": "/bin/bash",
"Args": [],
"State": {
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 0,
"ExitCode": 0,
"Error": "",
"StartedAt": "2019-07-31T03:15:26.09471362Z",
"FinishedAt": "2019-07-31T03:15:27.970398517Z"
},
"Image": "sha256:3556258649b2ef23a41812be17377d32f568ed9f45150a26466d2ea26d926c32",
"ResolvConfPath": "/var/lib/docker/containers/67481376c1dbd16f2cdb45f95dbc89758df1ae267289f96aca286242dab36578/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/67481376c1dbd16f2cdb45f95dbc89758df1ae267289f96aca286242dab36578/hostname",
"HostsPath": "/var/lib/docker/containers/67481376c1dbd16f2cdb45f95dbc89758df1ae267289f96aca286242dab36578/hosts",
"LogPath": "/var/lib/docker/containers/67481376c1dbd16f2cdb45f95dbc89758df1ae267289f96aca286242dab36578/67481376c1dbd16f2cdb45f95dbc89758df1ae267289f96aca286242dab3
6578-json.log", "Name": "/unruffled_mahavira",
"RestartCount": 0,
"Driver": "overlay",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"ConsoleSize": [
0,
0
],
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DiskQuota": 0,
"KernelMemory": 0,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": -1,
"OomKillDisable": false,
"PidsLimit": 0,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0
},
"GraphDriver": {
"Name": "overlay",
"Data": {
"LowerDir": "/var/lib/docker/overlay/688f7629e585caacaa7e6e584a6c9caa8a4674cced37329df1ddac6e97b91f09/root",
"MergedDir": "/var/lib/docker/overlay/0552e76e57e334d1f6430054a619f7f3c992b8f8aca582764ab391b98bcd4703/merged",
"UpperDir": "/var/lib/docker/overlay/0552e76e57e334d1f6430054a619f7f3c992b8f8aca582764ab391b98bcd4703/upper",
"WorkDir": "/var/lib/docker/overlay/0552e76e57e334d1f6430054a619f7f3c992b8f8aca582764ab391b98bcd4703/work"
}
},
"Mounts": [],
"Config": {
"Hostname": "67481376c1db",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"Image": "ubuntu",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "ad68e2577a7ebe43ec48ba6768f04c06dc169891e687115d6ab75de60f3eb4d5",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": null,
"SandboxKey": "/var/run/docker/netns/ad68e2577a7e",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "b8c608e9ba75a173d2d4dc89947f75d7c97204e874382dfb75d4806dcf6648ac",
"EndpointID": "",
"Gateway": "",
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": ""
}
}
}
}
]
[root@docker ~]#

自定义容器的名字

1
2
3
4
5
6
7
[root@docker ~]# docker container run -it --name mwj ubuntu		#在启动容器时指定名字,不能重复使用已有的名字
root@07905cebf525:/# exit
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07905cebf525 ubuntu "/bin/bash" 27 seconds ago Exited (0) 15 seconds ago mwj
67481376c1db ubuntu "/bin/bash" 15 minutes ago Exited (0) 15 minutes ago unruffled_mahavira
a0de49b1f37b ubuntu "cat /etc/lsb-release" 15 minutes ago Exited (0) 15 minutes ago sleepy_wozniak

重新启动已经停止的容器

1
2
3
4
5
6
7
[root@docker ~]# docker container ls -a		#以交互的方式进入一个已经退出的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07905cebf525 ubuntu "/bin/bash" 21 minutes ago Exited (0) 30 seconds ago mwj
67481376c1db ubuntu "/bin/bash" 36 minutes ago Exited (0) 36 minutes ago unruffled_mahavira
a0de49b1f37b ubuntu "cat /etc/lsb-release" 36 minutes ago Exited (0) 36 minutes ago sleepy_wozniak
[root@docker ~]# docker start -i mwj #不加-i参数不会进入容器
root@07905cebf525:/#

删除已经停止的容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@docker ~]# docker container ls -a		#只能删除已经停止的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07905cebf525 ubuntu "/bin/bash" 4 hours ago Up 4 hours mwj
67481376c1db ubuntu "/bin/bash" 4 hours ago Exited (0) 4 hours ago unruffled_mahavira
a0de49b1f37b ubuntu "cat /etc/lsb-release" 4 hours ago Exited (0) 4 hours ago sleepy_wozniak
[root@docker ~]# docker rm a0de49b1f37b
a0de49b1f37b
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07905cebf525 ubuntu "/bin/bash" 4 hours ago Up 4 hours mwj
67481376c1db ubuntu "/bin/bash" 4 hours ago Exited (0) 4 hours ago unruffled_mahavira
[root@docker ~]#

[root@docker ~]# docker container run -it --rm --name="test" centos:7.6.1810 /bin/bash #添加--rm参数可以在退出容器时自动将容器删除
[root@ffd9ef6d97cb /]#
[root@ffd9ef6d97cb /]#
[root@ffd9ef6d97cb /]# exit
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07905cebf525 ubuntu "/bin/bash" 4 hours ago Up 4 hours mwj
67481376c1db ubuntu "/bin/bash" 4 hours ago Exited (0) 4 hours ago unruffled_mahavira
[root@docker ~]#

Docker守护式容器

什么是守护式容器?

  1. 能够长期运行
  2. 没有交互式会话
  3. 非常适合运行应用程序或者服务

以守护形式运行容器

1
2
3
4
5
6
[root@docker ~]# docker container run -it centos:7.6.1810 /bin/bash
[root@67ff1e2c55c2 /]# [root@docker ~]# #Ctrl+PQ退出并将容器放到后台运行
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
67ff1e2c55c2 centos:7.6.1810 "/bin/bash" 21 seconds ago Up 20 seconds eloquent_hopper
[root@docker ~]#

启动守护式容器

1
2
3
4
5
6
[root@docker ~]# docker container run -d --name="shell" centos:7.6.1810 /bin/bash -c "while true;do echo hello world; sleep 1;done"
4c4f3b0b5b7ad33eb283edf3d9791d1cb50aad616d1245374510f25135c1a972
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c4f3b0b5b7a centos:7.6.1810 "/bin/bash -c 'whi..." 9 seconds ago Up 8 seconds shell
[root@docker ~]# #在启动容器时执行一个死循环,让容器一直运行,如果只是单纯的加-d参数将容器放到后台,容器会是退出的状态

如何查看容器内部运行的情况呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@docker ~]# docker logs -f -t shell	#利用容器的日志logs去查看刚才执行死循环的容器,也可以使用tail命令查看
2019-07-31T08:28:42.044371339Z hello world
2019-07-31T08:28:43.049225671Z hello world
2019-07-31T08:28:44.050978845Z hello world
2019-07-31T08:28:45.053612590Z hello world
2019-07-31T08:28:46.054194159Z hello world
2019-07-31T08:28:47.055889712Z hello world
2019-07-31T08:28:48.057540194Z hello world
2019-07-31T08:28:49.058689431Z hello world
2019-07-31T08:28:50.061623553Z hello world
2019-07-31T08:28:51.062316325Z hello world
2019-07-31T08:28:52.063958674Z hello world
2019-07-31T08:28:53.066595699Z hello world
2019-07-31T08:28:54.067589329Z hello world
2019-07-31T08:28:55.069078651Z hello world
2019-07-31T08:28:56.070604546Z hello world
2019-07-31T08:28:57.073304208Z hello world
2019-07-31T08:28:58.075061319Z hello world

查看容器内部的进程

1
2
3
4
5
[root@docker ~]# docker top shell	#容器内部运行的进程情况
UID PID PPID C STIME TTY TIME CMD
root 14396 14384 0 16:28 ? 00:00:00 /bin/bash -c while true;do echo
hello world; sleep 1;doneroot 15044 14396 0 16:37 ? 00:00:00 sleep 1
[root@docker ~]#

在已经运行的容器启动新的进程

1
2
3
4
5
6
7
8
[root@docker ~]# docker exec -it shell /bin/bash
[root@4c4f3b0b5b7a /]# [root@docker ~]# #ctrl+PQ退出
[root@docker ~]# docker top shell #容器后台多了一个进程
UID PID PPID C STIME TTY TIME CMD
root 14396 14384 0 16:28 ? 00:00:00 /bin/bash -c while true;do echo h
ello world; sleep 1;doneroot 16113 16104 0 16:47 pts/0 00:00:00 /bin/bash
root 16140 14396 0 16:47 ? 00:00:00 sleep 1
[root@docker ~]#

停止守护式容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d899667a2160 ubuntu "/bin/bash" 2 seconds ago Exited (0) 1 second ago stoic_mayer
4c4f3b0b5b7a centos:7.6.1810 "/bin/bash -c 'whi..." 32 minutes ago Up 32 minutes shell
[root@docker ~]# docker stop shell #会发送命令给容器,有一个停止的过程
shell
[root@docker ~]#

[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d899667a2160 ubuntu "/bin/bash" 2 minutes ago Exited (0) 20 seconds ago stoic_mayer
4c4f3b0b5b7a centos:7.6.1810 "/bin/bash -c 'whi..." 35 minutes ago Up 4 seconds shell
[root@docker ~]# docker kill shell #立刻停止容器,不需要等待,可能会造成数据丢失
shell
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d899667a2160 ubuntu "/bin/bash" 2 minutes ago Exited (0) 30 seconds ago stoic_mayer
4c4f3b0b5b7a centos:7.6.1810 "/bin/bash -c 'whi..." 35 minutes ago Exited (137) 2 seconds ago shell
[root@docker ~]#

容器中部署静态网站

启动Ubuntu容器

1
2
[root@docker ~]# docker container run -p 80 --name="web" -it ubuntu /bin/bash	--将容器的80端口映射到宿主机的随机端口
root@67cdc97159eb:/# apt-get install -y nginx #安装nginx

配置NGINX

1
2
3
[root@ec4c9bdbd2fb /]# cat /usr/share/nginx/html/index.html	
Test Nginx
[root@ec4c9bdbd2fb /]# nginx #启动nginx

浏览器查看

先查看端口映射

1
2
3
4
[root@docker ~]# docker container ls -a		#由于前面定义的是随机宿主机的端口,现在看到宿主机的32769端口被映射到容器的80端口
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ec4c9bdbd2fb centos:7.6.1810 "/bin/bash" 55 minutes ago Up 55 minutes 0.0.0.0:32769->80/tcp web
[root@docker ~]#

访问测试

1
2
3
[root@docker ~]# curl http://10.0.0.23:32769	#可以直观的看到宿主机的32769端口会被跳转到容器的80端口
Test Nginx
[root@docker ~]#

浏览器访问

端口映射的方式

将容器所有公开的端口发布到宿主机随机端口

1
[root@docker ~]# docker run -P -it ubuntu /bin/bash

指定映射容器的那些端口

只指定容器的端口

1
[root@docker ~]# docker run -p 80 -it ubuntu /bin/bash	#将容器的80端口映射到宿主机的随机端口

指定宿主机和容器的端口

1
[root@docker ~]# docker run -p 8080:80 -it ubuntu /bin/bash		#将宿主机的8080端口映射到容器的80端口

指定IP地址和宿主机、容器的端口

1
[root@docker ~]# docker run -p 10.0.0.23:8080:80 -it ubuntu /bin/bash	#将访问宿主机10.0.0.23:80地址的转发到容器的80端口

指定IP地址和容器的端口

1
docker run -p 172.16.1.23::80 -it ubuntu /bin/bash		#将宿主机172.16.1.23网卡的一个随机端口映射到容器的80端口

查看端口映射情况

1
2
3
4
5
[root@docker ~]# docker container  ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6a2074e850dc ubuntu "/bin/bash" 2 minutes ago Up 2 minutes 172.16.1.23:32768->80/tcp adoring_gates
bbeb304963a0 ubuntu "/bin/bash" 5 minutes ago Up 5 minutes 10.0.0.23:8080->80/tcp gifted_curran
[root@docker ~]#

查看和删除镜像

镜像存放的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[root@docker ~]# ll /var/lib/docker/
total 36
drwx------ 4 root root 4096 Aug 1 09:28 containers
drwx------ 3 root root 4096 Jul 30 21:57 image
drwxr-x--- 3 root root 4096 Jul 30 21:57 network
drwx------ 13 root root 4096 Aug 1 09:28 overlay
drwx------ 4 root root 4096 Jul 30 21:57 plugins
drwx------ 2 root root 4096 Jul 30 21:57 swarm
drwx------ 2 root root 4096 Jul 31 10:51 tmp
drwx------ 2 root root 4096 Jul 30 21:57 trust
drwx------ 2 root root 4096 Jul 30 21:57 volumes
[root@docker ~]#

[root@docker ~]# docker info #使用命令查看镜像存放位置,Docker Root Dir就是镜像目录
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 4
Server Version: 17.03.2-ce
Storage Driver: overlay
Backing Filesystem: extfs
Supports d_type: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc
runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe
init version: 949e6fa
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-957.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 972.6 MiB
Name: docker
ID: DOBJ:26YX:KARR:N4NN:IN6G:AFTW:KPBG:PYCL:B5TD:JBAP:WL4W:MRDI
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
127.0.0.0/8
Registry Mirrors:
https://265wemgl.mirror.aliyuncs.com
Live Restore Enabled: false

列出镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-a	显示所有的镜像,默认不显示中间层的镜像
-f 显示时的过滤条件
--no-trunc 不使用截断镜像唯一ID的方式显示
-q 只显示镜像的唯一ID
[root@docker ~]# docker images #旧版显示,docker版本较低的只能使用此命令查看
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 3556258649b2 8 days ago 64.2 MB
centos 7.6.1810 f1cb7c7d58b7 4 months ago 202 MB
centos latest 9f38484d220f 4 months ago 202 MB
hello-world latest fce289e99eb9 7 months ago 1.84 kB
[root@docker ~]# docker image ls #新版命令,兼容docker images显示
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 3556258649b2 8 days ago 64.2 MB
centos 7.6.1810 f1cb7c7d58b7 4 months ago 202 MB
centos latest 9f38484d220f 4 months ago 202 MB
hello-world latest fce289e99eb9 7 months ago 1.84 kB
[root@docker ~]#
  1. REPOSITORY:仓库
  2. TAG:标签,用于标识同一仓库下镜像的不同版本
  3. IMAGE ID:镜像为唯一标识
  4. CREATED:镜像的创建时间
  5. SIZE:镜像的大小

查看镜像的详细内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
[root@docker ~]# docker inspect centos:7.6.1810 
[
{
"Id": "sha256:f1cb7c7d58b73eac859c395882eec49d50651244e342cd6c68a5c7809785f427",
"RepoTags": [
"centos:7.6.1810"
],
"RepoDigests": [
"centos@sha256:62d9e1c2daa91166139b51577fe4f4f6b4cc41a3a2c7fc36bd895e2a17a3e4e6"
],
"Parent": "",
"Comment": "",
"Created": "2019-03-14T21:20:29.635970966Z",
"Container": "cc6043a787f6d1c7ae3e121ebdf1c4478186336aa7274871780a0a7bcc3a061a",
"ContainerConfig": {
"Hostname": "cc6043a787f6",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/bash\"]"
],
"ArgsEscaped": true,
"Image": "sha256:698a0848ee35389ab7b98494bdc60f887c54ddb94fc2326a1fb4eff8895aff43",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20181204",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"DockerVersion": "18.06.1-ce",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/bash"
],
"ArgsEscaped": true,
"Image": "sha256:698a0848ee35389ab7b98494bdc60f887c54ddb94fc2326a1fb4eff8895aff43",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20181204",
"org.label-schema.license": "GPLv2",
"org.label-schema.name": "CentOS Base Image",
"org.label-schema.schema-version": "1.0",
"org.label-schema.vendor": "CentOS"
}
},
"Architecture": "amd64",
"Os": "linux",
"Size": 201756323,
"VirtualSize": 201756323,
"GraphDriver": {
"Name": "overlay",
"Data": {
"RootDir": "/var/lib/docker/overlay/7805437da00b08442f662a3d83fa728b7afc3f2ef60f296e2506330565ce5f87/root"
}
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:89169d87dbe2b72ba42bfbb3579c957322baca28e03a1e558076542a1c1b2b4a"
]
}
}
]
[root@docker ~]#

删除镜像

1
2
3
4
5
6
7
8
9
[root@docker ~]# docker rmi centos 	#可以是镜像名称或者是镜像ID
Untagged: centos:latest
Untagged: centos@sha256:a799dd8a2ded4a83484bbae769d97655392b3f86533ceb7dd96bbac929809f3c
Deleted: sha256:9f38484d220fa527b1fb19747638497179500a1bed8bf0498eb788229229e6e1
Deleted: sha256:d69483a6face4499acb974449d1303591fcbb5cdce5420f36f8a6607bda11854
[root@docker ~]#

[root@docker ~]# docker rmi $(docker image ls -a -q) #删除所有镜像
[root@docker ~]# docker image ls -a -q |xargs rmi #删除所有镜像

获取和推送镜像

搜索镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@docker ~]# docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating s... 9787 [OK]
dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interfac... 327 [OK]
rastasheep/ubuntu-sshd Dockerized SSH service, built on top of of... 226 [OK]
consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC sessi... 184 [OK]
ubuntu-upstart Upstart is an event-based replacement for ... 99 [OK]
ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 97 [OK]
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 50 [OK]
ubuntu-debootstrap debootstrap --variant=minbase --components... 40 [OK]
i386/ubuntu Ubuntu is a Debian-based Linux operating s... 18
1and1internet/ubuntu-16-apache-php-5.6 ubuntu-16-apache-php-5.6 14 [OK]
ppc64le/ubuntu Ubuntu is a Debian-based Linux operating s... 13
1and1internet/ubuntu-16-apache-php-7.0 ubuntu-16-apache-php-7.0 13 [OK]
eclipse/ubuntu_jdk8 Ubuntu, JDK8, Maven 3, git, curl, nmap, mc... 11 [OK]
1and1internet/ubuntu-16-nginx-php-phpmyadmin-mariadb-10 ubuntu-16-nginx-php-phpmyadmin-mariadb-10 11 [OK]
1and1internet/ubuntu-16-nginx-php-5.6 ubuntu-16-nginx-php-5.6 8 [OK]
1and1internet/ubuntu-16-nginx-php-5.6-wordpress-4 ubuntu-16-nginx-php-5.6-wordpress-4 7 [OK]
1and1internet/ubuntu-16-apache-php-7.1 ubuntu-16-apache-php-7.1 6 [OK]
darksheer/ubuntu Base Ubuntu Image -- Updated hourly 5 [OK]
1and1internet/ubuntu-16-nginx-php-7.0 ubuntu-16-nginx-php-7.0 4 [OK]
1and1internet/ubuntu-16-apache-php-5.6-zend-2 ubuntu-16-apache-php-5.6-zend-2 2 [OK]
pivotaldata/ubuntu A quick freshening-up of the base Ubuntu d... 2
1and1internet/ubuntu-16-php-7.1 ubuntu-16-php-7.1 1 [OK]
1and1internet/ubuntu-16-sshd ubuntu-16-sshd 1 [OK]
smartentry/ubuntu ubuntu with smartentry 1 [OK]
pivotaldata/ubuntu-gpdb-dev Ubuntu images for GPDB development 0
[root@docker ~]#

拉取镜像

1
2
3
4
5
6
7
8
9
[root@docker ~]# docker pull centos:7.6.1810	#不指定镜像的版本默认拉取最新的
7.6.1810: Pulling from library/centos
ac9208207ada: Pull complete
Digest: sha256:62d9e1c2daa91166139b51577fe4f4f6b4cc41a3a2c7fc36bd895e2a17a3e4e6
Status: Downloaded newer image for centos:7.6.1810
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7.6.1810 f1cb7c7d58b7 4 months ago 202 MB
[root@docker ~]#

推送镜像

首先去docker hub注册账号

1
2
3
4
5
6
7
8
9
10
[root@docker ~]# docker tag f1cb7c7d58b7 missf2013/centos	#docker只会推送修改的部分镜像,直接推送未修改的镜像会出错
[root@docker ~]# docker login --登录
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: missf2013 --docker hub的用户名
Password: #密码
Login Succeeded
[root@docker ~]# docker push missf2013/centos
The push refers to a repository [docker.io/missf2013/centos]
89169d87dbe2: Pushing [==> ] 11.97 MB/201.8 MB
#推送成功之后,登录自己的docker hub就能看到自己推送上来的镜像

构建镜像

什么是构建镜像?

  1. 保存对容器的修改,并再次使用
  2. 自定义镜像的能力
  3. 以软件的形式打包并分发服务器及其运行的环境
  4. 在其他主机上可以运行某个定义好的镜像,更方便的提供服务

两种构建镜像的方式

通过容器构建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-a	一般指定镜像的作者和联系方式
-m 构建镜像的说明
-p 可以不暂停容器进行构建
[root@docker ~]# docker container run -it centos:7.6.1810 #启动一个容器
[root@0bf0d905a865 /]# yum install -y nginx #做相应的修改
[root@docker ~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0bf0d905a865 centos:7.6.1810 "/bin/bash" About a minute ago Up About a minute dazzling_bhabha
[root@docker ~]# docker commit -a "MoWenJie" -m "nginx" 0bf0d905a865 mwj/commit_nginx --对一个运行中的容器镜像构建
sha256:1f14b0232e4bc0c5054b974d825d1bd8586e269cd0be9338163cb203c9660ff1
[root@docker ~]# docker image ls -a #可以看到新构建的镜像,容器再次启动是构建之后的环境
REPOSITORY TAG IMAGE ID CREATED SIZE
mwj/commit_nginx latest 1f14b0232e4b 9 seconds ago 293 MB
centos 7.6.1810 f1cb7c7d58b7 4 months ago 202 MB
missf2013/centos latest f1cb7c7d58b7 4 months ago 202 MB
mowenjie/centos latest f1cb7c7d58b7 4 months ago 202 MB
[root@docker ~]#

通过Dockerfile构建镜像

什么是dockerfile?

Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像

dockerfile的基本结构

Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令

dockerfile文件说明

Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM,如果在同一个Dockerfile中创建多个镜像时,可以使用多个 FROM 指令

通过dockerfile构建nginx

1.在宿主机上创建工作目录

1
2
3
4
5
[root@docker ~]# ll /dockerfile/nginx/		#编写dockerfile和启动脚本存放的目录
total 8
-rw-r--r-- 1 root root 471 Aug 5 09:27 dockerfile
-rw-r--r-- 1 root root 40 Aug 5 09:11 run.sh
[root@docker ~]#

2.dockerfile文件内容详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@docker ~]# cat /dockerfile/nginx/dockerfile
FROM centos:7.6.1810 #指定要用那个镜像来构建,不指定tag的话默认使用最新的
MAINTAINER this is nginx image <mwj> #维护者信息
RUN yum install -y wget proc-devel net-tools gcc zlib-devel make openssl-devel #安装依赖
RUN wget http://nginx.org/download/nginx-1.9.9.tar.gz #下载nginx安装包
RUN tar zxvf nginx-1.9.9.tar.gz #解压
WORKDIR nginx-1.9.9 #切换到解压后的目录
RUN ./configure --prefix=/usr/local/nginx && make && make install #编译安装
EXPOSE 80 #容器暴露自己的端口
EXPOSE 443
RUN echo "daemon off;" >>/usr/local/nginx/conf/nginx.conf #关闭守护进程
WORKDIR /dockerfile/nginx #切换到宿主机上的工作目录
ADD run.sh /run.sh #创建run.sh启动文件
RUN chmod 755 /run.sh
CMD ["/run.sh"] #容器启动时所运行的命令
[root@docker ~]#

3.启动脚本的内容

1
2
3
4
[root@docker ~]# cat /dockerfile/nginx/run.sh 
#!/bin/bash
/usr/local/nginx/sbin/nginx
[root@docker ~]#

4.生成镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[root@docker ~]# cd /dockerfile/nginx/ && ll	#切换到dockerfile文件所在的目录
total 8
-rw-r--r-- 1 root root 484 Aug 5 23:01 dockerfile
-rw-r--r-- 1 root root 40 Aug 5 09:11 run.sh
[root@docker nginx]# docker build -t "mwj/nginx:test" . #在当前目录构建镜像
Sending build context to Docker daemon 3.072 kB
Step 1/14 : FROM centos:7.6.1810
---> f1cb7c7d58b7
Step 2/14 : MAINTAINER this is nginx image <mwj>
---> [Warning] IPv4 forwarding is disabled. Networking will not work.
---> Running in 07edb137e1a9
---> 5eeae1d37b2a
...... --部分过程省略
Removing intermediate container f60ac000f547
Step 8/14 : EXPOSE 80
---> Running in 7167f87d5461
---> ec2a78995353
Removing intermediate container 7167f87d5461
Step 9/14 : EXPOSE 443
---> Running in a904fc8e3657
---> 737ed545b329
Removing intermediate container a904fc8e3657
Step 10/14 : RUN echo "daemon off;" >>/usr/local/nginx/conf/nginx.conf
---> Running in 7a71bbf8e5bc
---> 6f07999206e2
Removing intermediate container 7a71bbf8e5bc
Step 11/14 : WORKDIR /dockerfile/nginx
---> 222b78ff2097
Removing intermediate container 3e37db11a06a
Step 12/14 : ADD run.sh /run.sh
---> e877e927d669
Removing intermediate container 9bb5b7f5a796
Step 13/14 : RUN chmod 755 /run.sh
---> Running in 33bdfff9dc37
---> 15ca51fc522d
Removing intermediate container 33bdfff9dc37
Step 14/14 : CMD /run.sh
---> Running in 93007fe6278a
---> 4c941145fccd
Removing intermediate container 93007fe6278a
Successfully built 4c941145fccd

5.启动容器并测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@docker nginx]# docker image ls	#查看新构建的镜像nginx:test
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx test 4c941145fccd About a minute ago 417 MB
nginx latest e445ab08b2be 12 days ago 126 MB
ubuntu latest 3556258649b2 12 days ago 64.2 MB
centos 7.6.1810 f1cb7c7d58b7 4 months ago 202 MB
centos latest 9f38484d220f 4 months ago 202 MB
[root@docker nginx]# docker container run -d -P nginx:test #启动容器
88fe466c011f94623f410f7c54f8182ab07e0b015a92287fd2f5bf9fd336b31d
[root@docker ~]# docker container ls -a #查看容器的端口映射到宿主机的那个端口
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES88fe466c011f nginx:test "/run.sh" 25 minutes ago Up 25 minutes 0.0.0.0:32771->80/tcp, 0.0.0.0:32770->443/tcp
blissful_goldstine
[root@docker ~]#

6.浏览器访问

Docker远程连接

docker的c/s模式

前面我们说过,Docker是基于C/S架构的程序,docker的客户端(就是我们的命令行)通过发送请求命令给Docker守护进程(docker daemon),Docker守护进程返回执行结果给客户端,然后显示在命令行界面。客户端和守护进程可以是在一台机器上,也可以是在不同的机器上,现在我们就来配置docker的远程连接。

修改docker的启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@docker ~]# cat /lib/systemd/system/docker.service 
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target firewalld.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock #添加docker的连接方式
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
[Install]
WantedBy=multi-user.target
[root@docker ~]#

重启docker

1
2
3
4
5
6
7
[root@docker ~]# systemctl daemon-reload
[root@docker ~]# systemctl restart docker.service
[root@docker ~]# ps -ef |grep docker #可以看到docker守护进程已经在监听tcp2375端口
root 17801 1 0 10:26 ? 00:00:00 /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
root 17804 17801 0 10:26 ? 00:00:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-time
out 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runcroot 18001 7641 0 10:47 pts/0 00:00:00 grep --color=auto docker
[root@docker ~]#

远程连接测试

浏览器测试

使用另一台机器测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@k8s-m ~]# docker -H tcp://10.0.0.23:2375 images 	#连接到10.0.0.23主机可以看到主机上的镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx test 4c941145fccd About an hour ago 416.6 MB
nginx latest e445ab08b2be 12 days ago 125.8 MB
ubuntu latest 3556258649b2 12 days ago 64.18 MB
centos 7.6.1810 f1cb7c7d58b7 4 months ago 201.8 MB
centos latest 9f38484d220f 4 months ago 201.8 MB
[root@k8s-m ~]#
[root@k8s-m ~]# docker -H tcp://10.0.0.23:2375 rmi ubuntu #可以使用远程的方式执行操作
Untagged: ubuntu:latest
Untagged: ubuntu@sha256:c303f19cfe9ee92badbbbd7567bc1ca47789f79303ddcef56f77687d4744cd7a
Deleted: sha256:3556258649b2ef23a41812be17377d32f568ed9f45150a26466d2ea26d926c32
Deleted: sha256:e68a9307017f6b268915b4d1b537ff663ff6967a37c85bd03a26f2e171ee9f6f
Deleted: sha256:ed8308579f11f616d6b58e6e456f765f8e3837f69f81f7304f213c4e3aa96856
Deleted: sha256:a757708db54bb9fe5cc7962e8890e008992209d6eca7d6556db03d2891159fef
Deleted: sha256:543791078bdb84740cb5457abbea10d96dac3dea8c07d6dc173f734c20c144fe

Docker的基础网络类型

docker的四种网络类型

1
2
3
4
5
[root@docker ~]# docker network ls		#这里只能看到三种,还有一种网络类型是container
NETWORK ID NAME DRIVER SCOPE
a9eb3a40813d bridge bridge local
7fa413c3bb93 host host local
96b447ead50e none null local

Bridge桥接模式

bridge桥接模式是容器启动时默认的网络模式,类似NAT模式,也可以用–net参数指定使用哪种网络模式启动容器。docker在启动时会创建一个虚拟网桥docker0,默认地址为172.17.0.1/16,容器启动后都会被桥接到docker0上,并自动分配到一个IP地址,进入容器使用ifconfig命令可以看到。

启动两个容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@docker nginx]# docker run -it #name test1 mwj/nginx1 /bin/bash	--启动第一个容器
[root@fd1dadb0cbd9 nginx]# ifconfig #IP地址为172.17.0.2
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:2 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 7 bytes 586 (586.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7 bytes 586 (586.0 B)
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
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
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@fd1dadb0cbd9 nginx]#

[root@docker ~]# docker run -it #name test2 mwj/nginx2 /bin/bash --启动第二个容器
[root@246b09019a45 nginx]# ifconfig #IP地址为172.17.0.3
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe11:3 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 6 bytes 516 (516.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6 bytes 516 (516.0 B)
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
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
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@246b09019a45 nginx]#

容器间能互相ping通

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[root@fd1dadb0cbd9 nginx]# 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.145 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.042 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.044 ms

[root@246b09019a45 nginx]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.043 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.046 ms

[root@246b09019a45 nginx]# curl http://172.17.0.2 #同时也能互相访问彼此的nginx服务
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@246b09019a45 nginx]#

Host网络模式

host网络模式可以直接使用宿主机的IP地址与外界通信,若宿主机的eth0是一个公网的IP地址,那么容器同时也拥有了这个公网IP,而且容器内服务的端口也是使用宿主机的端口,无需通过NAT转换。这样无需再映射容器与宿主机之间的端口,但是会造成网络环境隔离性弱化,容器不再拥有隔离的网络,独立的网络。由于网络隔离性的弱化,该容器会与宿主机共享竞争网络资源和端口资源。

使用host网络模式启动容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@docker ~]# docker run -it --name host_test --net host centos:7.6.1810
[root@docker /]# docker #看不出来变化,是因为主机名也是和宿主机一样,但是容器内是没有docker命令的
bash: docker: command not found
[root@docker /]# ip addr show #查看IP完全和宿主机查看一样
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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:65:ca:77 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.23/24 brd 10.0.0.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
3: ens35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:65:ca:81 brd ff:ff:ff:ff:ff:ff
inet 172.16.1.23/24 brd 172.16.1.255 scope global noprefixroute ens35
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe65:ca81/64 scope link
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:97:ac:69:e1 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:97ff:feac:69e1/64 scope link
valid_lft forever preferred_lft forever
[root@docker /]#

Container网络模式

启动一个容器con1(被共享网络环境的容器),再启动一个容器con2(需要共享其他网络的容器),con2容器使用的是con1容器的命名空间(namespace),这种模式可以更好服务容器间的通信,docker可以通过localhost来访问命名空间下的其他容器,传输效率较高,虽然多个容器共享网络环境,但是多个容器形成的整体依然与宿主机以及其他容器形成网络隔离。

1
2
[root@docker ~]# docker container run -it --name con1 --net host centos:7.6.1810	#con1使用host网络模式
[root@docker ~]# docker container run -it --name con2 --net container:con1 centos:7.6.1810 #con2直接使用了con1的网络

None网络模式

网络环境为none,即不做任何网络环境的设定,容器内部就只能使用loopback网络设备,不会再有其他的网络资源。这样网络方式的用途是,将网络创建的责任完全交给用户,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发,这种方式可以实现更加灵活复杂的网络,同时也体现了Docker设计理念的开放。

1
2
3
4
5
6
7
8
[root@docker ~]# docker container run -it --name mwj1 --net none centos:7.6.1810
[root@7beccfd72b65 /]# ifconfig #只能看到loopback网络设备
1: lo: mtu 65536 qdisc noqueue state UNKNOWN
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

Docker的数据卷

什么是数据卷?

数据卷(Data volume)是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问。可以简单的理解为:就是将宿主机的一个目录和容器的一个目录做了NFS,两个目录下创建的数据会被同步。

关于UFS文件系统

联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。
联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

数据卷的设计目的

数据卷的设计目的,是为了使数据能够持久化,它和容器的生存周期完全独立,因此在容器被销毁是,docker不会删除容器所挂载的数据卷。

从图中可以看到,三个容器都挂载了同一个数据卷,就是宿主机上的一个目录,每个容器在自己的数据卷目录下写入数据,都会被持久化到宿主机的数据卷目录。

为容器添加数据卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@docker ~]# docker container run -v /mwj:/data -it centos:7.6.1810 /bin/bash	--将宿主机的/mwj目录映射到容器的/data目录
[root@551f34451c3b /]# ll / #容器中有了/data目录
total 60
-rw-r--r-- 9 root root 12053 Dec 4 2018 anaconda-post.log
lrwxrwxrwx 1 root root 7 Dec 4 2018 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Aug 7 13:53 data
drwxr-xr-x 5 root root 360 Aug 7 13:53 dev
drwxr-xr-x 1 root root 4096 Aug 7 13:53 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Dec 4 2018 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Dec 4 2018 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 97 root root 0 Aug 7 13:53 proc
dr-xr-x--- 2 root root 4096 Dec 4 2018 root
drwxr-xr-x 11 root root 4096 Dec 4 2018 run
lrwxrwxrwx 1 root root 8 Dec 4 2018 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Aug 5 01:22 sys
drwxrwxrwt 7 root root 4096 Dec 4 2018 tmp
drwxr-xr-x 13 root root 4096 Dec 4 2018 usr
drwxr-xr-x 18 root root 4096 Dec 4 2018 var
[root@551f34451c3b /]# cd data/
[root@551f34451c3b data]# touch datavolume #在data目录创建文件
[root@551f34451c3b data]# [root@docker ~]# #Ctrl p+q退出
[root@docker ~]# ll /mwj/ #容器中的数据被持久化到宿主机
total 0
-rw-r--r-- 1 root root 0 Aug 7 21:54 datavolume
[root@docker ~]#

数据卷的权限设置

1
2
3
4
[root@docker ~]# docker container run -v /mwj:/data:ro -it --name test1 centos:7.6.1810 /bin/bash	#启动容器时设置只读
[root@871d945acf7c /]# touch /data/123 #容器无法创建文件
touch: cannot touch '/data/123': Read-only file system
[root@871d945acf7c /]#

Docker的数据卷容器

数据卷容器挂载了一个宿主机的本地目录,其他容器通过连接数据卷容器来实现数据的共享。

制作数据卷容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@docker ~]# cat /dockerfile/volume/dockerfile	#dockerfile内容
FROM centos
VOLUME ["/datavolume1","/datavolume2"]
CMD /bin/bash
[root@docker volume]# docker build -t datavo1 .
Sending build context to Docker daemon 2.048 kB
Step 1/3 : FROM centos
---> 9f38484d220f
Step 2/3 : VOLUME /datavolume1 /datavolume2
---> Running in 36070367e4c7
---> 7fa566737d45
Removing intermediate container 36070367e4c7
Step 3/3 : CMD /bin/bash
---> Running in 31f938cd77fa
---> 5727bcde8e01
Removing intermediate container 31f938cd77fa
Successfully built 5727bcde8e01
[root@docker volume]#

启动数据卷容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@docker volume]# docker run -it --name dv1 datavo1
[root@0afdb9533882 /]# ll / #可以看到已经有了datavolume1和datavolume2数据卷
total 64
-rw-r--r-- 1 root root 12082 Mar 5 17:36 anaconda-post.log
lrwxrwxrwx 1 root root 7 Mar 5 17:34 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Aug 7 14:38 datavolume1
drwxr-xr-x 2 root root 4096 Aug 7 14:38 datavolume2
drwxr-xr-x 5 root root 360 Aug 7 14:38 dev
drwxr-xr-x 1 root root 4096 Aug 7 14:38 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Mar 5 17:34 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Mar 5 17:34 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 97 root root 0 Aug 7 14:38 proc
dr-xr-x--- 2 root root 4096 Mar 5 17:36 root
drwxr-xr-x 11 root root 4096 Mar 5 17:36 run
lrwxrwxrwx 1 root root 8 Mar 5 17:34 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Aug 5 01:22 sys
drwxrwxrwt 7 root root 4096 Mar 5 17:36 tmp
drwxr-xr-x 13 root root 4096 Mar 5 17:34 usr
drwxr-xr-x 18 root root 4096 Mar 5 17:34 var
[root@0afdb9533882 /]#

容器连接数据卷容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@docker ~]# docker run -it --name dv2 --volumes-from dv1 centos:7.6.1810 /bin/bash
#启动容器dv2时指定已经挂载数据卷的容器dv1
[root@e335b245323b /]# ll / #这时候dv1和dv2容器的数据卷目录已经可以共享数据
total 64
-rw-r--r-- 9 root root 12053 Dec 4 2018 anaconda-post.log
lrwxrwxrwx 1 root root 7 Dec 4 2018 bin -> usr/bin
drwxr-xr-x 2 root root 4096 Aug 7 14:38 datavolume1
drwxr-xr-x 2 root root 4096 Aug 7 14:38 datavolume2
drwxr-xr-x 5 root root 360 Aug 7 14:43 dev
drwxr-xr-x 1 root root 4096 Aug 7 14:43 etc
drwxr-xr-x 2 root root 4096 Apr 11 2018 home
lrwxrwxrwx 1 root root 7 Dec 4 2018 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Dec 4 2018 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 11 2018 media
drwxr-xr-x 2 root root 4096 Apr 11 2018 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2018 opt
dr-xr-xr-x 97 root root 0 Aug 7 14:43 proc
dr-xr-x--- 2 root root 4096 Dec 4 2018 root
drwxr-xr-x 11 root root 4096 Dec 4 2018 run
lrwxrwxrwx 1 root root 8 Dec 4 2018 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Apr 11 2018 srv
dr-xr-xr-x 13 root root 0 Aug 5 01:22 sys
drwxrwxrwt 7 root root 4096 Dec 4 2018 tmp
drwxr-xr-x 13 root root 4096 Dec 4 2018 usr
drwxr-xr-x 18 root root 4096 Dec 4 2018 var
[root@e335b245323b /]#

注意:dv2容器是通过连接数据卷容器dv1去挂载数据卷的,但即使数据卷容器dv1被销毁同时删除数据卷,dv2容器还是能使用数据卷的,就是说如果数据卷还被容器所使用,它就会一直存在。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@docker ~]# docker run -it --name dv3 datavo1	#启动dv3容器作为数据卷容器
[root@4cef0ed4be5e /]# ls
anaconda-post.log bin datavolume1 datavolume2 dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@4cef0ed4be5e /]# touch datavolume1/123
[root@4cef0ed4be5e /]# ll datavolume1/123
-rw-r--r-- 1 root root 0 Aug 8 01:09 datavolume1/123

[root@docker ~]# docker run --name dv4 -it --volumes-from dv3 centos:7.6.1810 /bin/bash #启动dv4容器挂载到dv3数据卷容器
[root@4c71b0b9f5cd /]# ls
anaconda-post.log bin datavolume1 datavolume2 dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@4c71b0b9f5cd /]# ll /datavolume1
total 0
-rw-r--r-- 1 root root 0 Aug 8 01:09 123
[root@4c71b0b9f5cd /]# touch /datavolume1/456

[root@docker ~]# docker rm -v dv3 #销毁数据卷容器并删除数据卷
dv3

[root@docker ~]# docker exec -it dv4 /bin/bash #即使数据卷容器dv3被删除,dv4容器依然能使用数据卷
[root@4c71b0b9f5cd /]# touch /datavolume1/789
[root@4c71b0b9f5cd /]# ll /datavolume1/789
-rw-r--r-- 1 root root 0 Aug 8 01:15 /datavolume1/789
[root@4c71b0b9f5cd /]#

数据卷的备份和还原

数据卷备份操作原理图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@docker ~]# docker exec -it dv4 /bin/bash		#备份dv4容器的/datavolume1数据卷
[root@4c71b0b9f5cd /]# ls /datavolume1/
123 456 789
[root@4c71b0b9f5cd /]# exit

[root@docker ~]# docker run --volumes-from dv4 -v /backup/:/con_backup --name dv5 centos:7.6.1810 tar cvf /con_backup/dv4.tar.gz /datavolume1/
tar: Removing leading `/' from member names
/datavolume1/
/datavolume1/456
/datavolume1/123
/datavolume1/789
[root@docker ~]# ls /backup/
dv4.tar.gz
[root@docker ~]#
#启动一个dv5容器,将dv4容器作为数据卷容器挂载,再把dv5容器的/con_backup和宿主机的/backup目录做数据卷映射,这个时候dv4容器数据卷的目录(需要备份的数据),和备份的目录(容器的/con_backup目录和宿主机的/backup目录)已经在一个容器内(dv5),执行tar命令将数据备份到容器的/con_backup/目录,这时候宿主机的/backup目录就有了备份的数据。

数据卷还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@docker ~]# docker exec -it dv4 /bin/bash		#删除dv4容器数据卷的数据
[root@4c71b0b9f5cd /]# ll /datavolume1/
total 0
-rw-r--r-- 1 root root 0 Aug 8 01:09 123
-rw-r--r-- 1 root root 0 Aug 8 01:13 456
-rw-r--r-- 1 root root 0 Aug 8 01:15 789
[root@4c71b0b9f5cd /]# rm -rf /datavolume1/*

[root@docker ~]# docker run --volumes-from dv4 -v /backup/:/con_backup --name dv5 centos:7.6.1810 tar xf /con_backup/dv4.tar.gz -C /datavolume1/
[root@docker ~]# docker exec -it dv4 /bin/bash
[root@4c71b0b9f5cd /]# ls /datavolume1/
datavolume1
[root@4c71b0b9f5cd /]# ls /datavolume1/datavolume1/ #由于备份数据的时候没有切换到/datavolume1里面在打包
123 456 789
文章作者: GZ
文章链接: https://gz1903.github.io/2019/11/14/容器化技术-Docker/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 GZ's Blog
打赏
  • 微信
  • 支付宝

评论