安装 Docker
1、卸载旧的版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-1atest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2、下载需要安装的包
yum install -y yum-utils
3、设置镜像仓库
# 推荐使用国内的镜像
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4、更新yum软件包索引
yum makecache fast
5、安装docker
# docker-ce 社区版 ee 企业版
yum install docker-ce docker-ce-cli containerd.io
6、启动docker
systemctl start docker
# 验证是否启动成功
docker version
7、运行Hello-world
docker run hello-world
8、卸载docker
# 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
# 删除资源文件
rm -rf /var/lib/docker
Docker run的运行流程
- docker首先在本机寻找镜像,判断本机是否存在这个镜像
- 如果有这个镜像,则使用此镜像运行;如果没有,则去docker hub 上下载镜像
- 在docker hub 上是否能找到此镜像
- 如果找到,则下载镜像到本地并运行;如果没有找到,则返回错误
Docker 底层原理
docker是如何进行工作的
Docker是一个Client - Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问。DockerServer接收到Docker-Client的指令,就会执行这个命令新建docker容器
docker为什么比vm快
Docker有着比虚拟机更少的抽象层。
docker利用的是宿主机的内核,vm需要是Guest Os。所以说,新建一个容器的时候,docker不需要像虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest oS ,分钟级别的,而docker是利用宿主机的操作系统吗,省略了这个复杂的过程,秒级!
Docker 常用命令
帮助命令
docker version # 查看docker版本
docker info # 查看docker详细信息
docker --help # 查看docker的所有命令
docker 命令 --help # 查看docker某个命令的参数信息
镜像命令
【docker images】 查看本地主机上的所有镜像
# 可选参数
-a,--all # 列出所有镜像
-q,--quiet # 只显示镜像的id
[root@zerollone ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres latest a373cbdcfe8b 2 weeks ago 418MB
# 解释说明
REPOSITORY 镜像的仓库源
TAG 镜像的标签
IMAGE ID 镜像的id
CREATED 镜像的创建时间
SIZE 镜像的大小
【docker search】 搜索镜像
[root@zerollone ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 14487 [OK]
mariadb MariaDB Server is a high performing open sou… 5529 [OK]
percona Percona Server is a fork of the MySQL relati… 621 [OK]
# 命令可选项,通过搜索来过滤
--fiter=STARS=3000 # 搜索STARS大于3000的镜像
[root@zerollone ~]# docker search mysql --filter=STARS=3000;
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 14487 [OK]
mariadb MariaDB Server is a high performing open sou… 5530 [OK]
【docker pull】 下载镜像
# 下载镜像
# docker pull 镜像名[:tag] tag表示版本
[root@zerollone ~]# docker pull mysql
Using default tag: latest # 如果不写tag,默认是latest,最新版本
latest: Pulling from library/mysql
5262579e8e45: Pull complete # 分层下载,docker image 的核心,联合文件系统
741b767e25b7: Pull complete
06e0c37837cf: Pull complete
c6f5d3670db7: Pull complete
d5c567b29c3e: Pull complete
6effcc6561c9: Pull complete
1e1493d45d9c: Pull complete
7101609fa7d9: Pull complete
432a1261dc2a: Pull complete
865a24d6d1f2: Pull complete
Digest: sha256:566007208a3f1cc8f9df6b767665b5c9b800fc4fb5f863d17aa1df362880ed04 # 签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 下载的真实地址
# 下面的命令等价
docker pull mysql
docker pull docker.io/library/mysql:latest
# 指定版本下载
[root@zerollone ~]# docker pull mysql:8.0
8.0: Pulling from library/mysql
5262579e8e45: Already exists # 与前面下载的镜像共用的文件
741b767e25b7: Already exists
06e0c37837cf: Already exists
c6f5d3670db7: Already exists
d5c567b29c3e: Already exists
323a74fdf36b: Pull complete
130e11b8eb71: Pull complete
e92f1f2dd77c: Pull complete
43c0f03962c9: Pull complete
6194c2f9ce13: Pull complete
a235a73ec4d4: Pull complete
Digest: sha256:a7a96a9dbf6f310703c4e0c61086b23c5835c33a05544cdc952a7cd0b8feb675
Status: Downloaded newer image for mysql:8.0
docker.io/library/mysql:8.0
【docker rmi】 删除镜像
docker rmi -f 镜像id # 删除指定的镜像
docker rmi -f 镜像id 镜像id 镜像id # 删除多个镜像
docker rmi -f $(docker images -aq) # 删除全部镜像
容器命令
说明:有了镜像才可以创建容器,下载一个centos镜像来测试学习,docker pull centos
新建容器并启动
docker run [可选参数] imageName
# 参数说明
--name="name" # 设置容器名字,用来与其他容器进行区分
-d # 以后台的方式运行
-it # 使用交互式方式运行, 进入容器查看内容
-p # 小写,指定容器的端口,-p 主机端口:容器端口
-P # 大写,随机指定端口
# 启动并进入容器
docker run -it centos /bin/bash
# 退出容器
exit
列出所有的运行的容器
docker ps 列出所有正在运行的容器
# 参数说明
-a # 列出当前正在运行的容器 + 历史运行的容器
-n=x # 列车最近运行的前x个容器
-q # 只显示容器的编号
退出容器
exit # 停止并退出容器
ctrl + p + q # 不停止但退出容器
删除容器
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器
docker rm -f 容器id # 可以删除正在运行的容器
docker rm -f $(docker ps -aq) # 删除所有的容器
启动重启停止杀死容器
docker start 容器id # 启动容器
docker restart 容器id # 重启容器
docker stop 容器id # 停止正在运行的容器
docker kill 容器id # 强制停止运行的容器
其他常用命令
后台启动容器
- docker run -d 容器id
docker run -d centos
# 启动后,运行 docker ps,发现 centos 停止并未运行
# 问题原因:
# docker 容器使用后台运行,就必须要有一个前台进程,docker 发现没有应用就会自动停止。
查看日志
- docker logs
# 参数说明
# -f 显示全部日志
# -t 显示日志的时间戳
# -n number 需要显示的日志条数,此命令等价于 --tail number
# 在centos中循环打印
docker run -d centos /bin/bash -c "while true;do echo hello;sleep 1;done"
# 查看centos容器的日志信息
docker logs -tf -n 10 容器id
docker logs -tf --tail 10 容器id
查看容器中进程信息
- docker top
# 命令 docker top 容器id
[root@zerollone ~]# docker top 3095
UID PID PPID C STIME TTY TIME CMD
799 1466 2663 0 10:25 ? 00:00:00 /bin/bash ********
799 2097 2663 0 10:26 ? 00:00:00 /bin/bash ********
799 2605 2586 0 Sep17 ? 00:00:00 /bin/bash ********
# 说明:
UID:当前用户id
PID:当前进程id
PPID:父进程id
查看镜像元数据
- docker inspect 镜像/容器id
[root@zerollone ~]# docker inspect 5d0da3dc9764
[
{
"Id": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"RepoTags": [
"centos:latest"
],
"RepoDigests": [
"centos@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177"
],
"Parent": "",
"Comment": "",
"Created": "2021-09-15T18:20:05.184694267Z",
"Container": "9bf8a9e2ddff4c0d76a587c40239679f29c863a967f23abf7a5babb6c2121bf1",
"ContainerConfig": {
"Hostname": "9bf8a9e2ddff",
"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\"]"
],
"Image": "sha256:f5b050f177fd426be8fe998a8ecf3fb1858d7e26dff4080b29a327d1bd5ba422",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"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": "20.10.7",
"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"
],
"Image": "sha256:f5b050f177fd426be8fe998a8ecf3fb1858d7e26dff4080b29a327d1bd5ba422",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
"org.label-schema.build-date": "20210915",
"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": 231268856,
"VirtualSize": 231268856,
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/cbf06b7f65308cab4597b5ee427702f2f4f9a87fd62b24937387681576134eb4/merged",
"UpperDir": "/var/lib/docker/overlay2/cbf06b7f65308cab4597b5ee427702f2f4f9a87fd62b24937387681576134eb4/diff",
"WorkDir": "/var/lib/docker/overlay2/cbf06b7f65308cab4597b5ee427702f2f4f9a87fd62b24937387681576134eb4/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:74ddd0ec08fa43d09f32636ba91a0a3053b02cb4627c35051aff89f853606b59"
]
},
"Metadata": {
"LastTagTime": "0001-01-01T00:00:00Z"
}
}
]
进入当前正在运行的容器
容器通常都是使用后台方式运行的,可能需要经常进入容器进行一些相关配置,进入正在运行的容器有两种命令
- docker exec -it 容器id bashshell
- docker attach 容器id
第一种方式:
[root@zerollone ~]# docker run -d centos /bin/bash -c "while true;do echo hello;sleep 100;done;"
28fc1a2e10e344fd72d771ac02840f72a4ba1ab24b4e4707e3302c4f2f423c6a
[root@zerollone ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28fc1a2e10e3 centos "/bin/bash -c 'while…" 4 seconds ago Up 3 seconds epic_proskuriakova
# 进入容器
[root@zerollone ~]# docker exec -it 28fc1a2e10e3 /bin/bash
[root@28fc1a2e10e3 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
第二种方式:
[root@zerollone ~]# docker attach 28fc1a2e10e3
hello
hello
hello
docker exec 和 docker attach 的区别
- docker exec 进入容器后开启一个新的终端,可以在里面进行命令操作
- docker attach 进入容器中正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
- docker cp 容器id:文件路径 物理机文件路径
# 进入docker容器
[root@zerollone ~]# docker run -it centos /bin/bash
[root@038f00b63edf /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@038f00b63edf /]# cd home/
[root@038f00b63edf home]# touch test.java
[root@038f00b63edf home]# ls
test.java
# 切换到本机
[root@zerollone ~]# ls
data docker-compose.yml thingsboard-3.4.4.rpm
[root@zerollone ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
038f00b63edf centos "/bin/bash" About a minute ago Up About a minute awesome_banzai
# 拷贝容器文件
[root@zerollone ~]# docker cp 038f00b63edf:/home/test.java /root
Successfully copied 1.54kB to /root
[root@zerollone ~]# ls
data docker-compose.yml test.java thingsboard-3.4.4.rpm
可视化
- portainer
- Rancher
什么是portainer
Docker图形化界面管理工具,提供一个后台面板供用户操作
# 命令
docker run -d -p 10003:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
测试访问:http://ip:10003
Docker 镜像详解
镜像是什么
镜像是一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包成docker镜像,就可以直接跑起来。
Docker镜像加载原理
UnionFS 联合文件系统
UnionFS(联合文件系统),联合文件系统是一种分层,轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特点:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的的文件和目录。
Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS.
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system),在bootfs之上。包含的就是典型Linux系统中的/dev、/proc、/bin、/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。
分层理解
通过下载一个镜像,观察下载日志的输出,可以看到镜像是一层一层被下载。
那么为什么Docker镜像要采用这种分层的结构呢
最大的好处莫过于是资源共享了。比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
查看镜像分层的方式可以通过docker image inspect命令。
说明
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版本。
这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。
Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker在 Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。
特点
- Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部
- 这一层就是我们通常说的容器层,容器之下的都叫镜像层!
commit镜像
提交一个自己的镜像,将自己主机里docker中的容器提交成一个新的版本。
- docker commit
# 具体命令
docker commit -m="提交容器的描述信息" -a="作者名" 容器id 镜像名:[tag]

容器数据卷
什么是容器卷
容器之间可以有一个数据共享的技术,docker容器中产生的数据,同步到本地,这就是卷技术,目录的挂载,将容器内的目录挂载到Linux中。
容器的持久化和同步操作,容器间也是可以数据共享的
使用数据卷
方式一:使用-v命令进行挂载
- docker run -it -v 主机目录地址:容器内目录地址 ….
# 测试
[root@zerollone ~]# pwd
/root
[root@zerollone ~]# ls
data docker-compose.yml test.java thingsboard-3.4.4.rpm
# 挂载
[root@zerollone ~]# docker run -it -v /root/centos_file:/home centos /bin/bash
# 容器内
[root@617b5b813dfc /]# cd home
[root@617b5b813dfc home]# ls
[root@617b5b813dfc home]# touch a.txt
[root@617b5b813dfc home]# ls
a.txt
[root@617b5b813dfc home]# exit
exit
# 主机内
[root@zerollone ~]# ls
centos_file data docker-compose.yml test.java thingsboard-3.4.4.rpm
[root@zerollone ~]# cd centos_file/
[root@zerollone centos_file]# ls
a.txt
可以通过docker inspect命令查看容器的挂载目录信息

使用数据卷是一个双向绑定的操作。即不论在容器内外操作文件,都会看到文件相应的变化
# 主机内
[root@zerollone centos_file]# cat a.txt
[root@zerollone centos_file]# vim a.txt
[root@zerollone centos_file]# cat a.txt
hello docker!!!
[root@zerollone centos_file]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
617b5b813dfc centos "/bin/bash" 30 minutes ago Up 8 minutes suspicious_villani
# 进入容器
[root@zerollone centos_file]# docker exec -it 617b5b813dfc /bin/bash
[root@617b5b813dfc /]# cd home/
[root@617b5b813dfc home]# cat a.txt
hello docker!!!
[root@617b5b813dfc home]#
安装MySQL
获取镜像
docker pull mysql:5.7运行容器,做数据挂载。同时启动mysql时,需要配置密码
docker run -d -p 3306:3306 -v /root/mysql/conf:/etc/mysql/conf.d -v /root/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 –name mysqlTest mysql:5.7说明:
-e 环境配置
匿名与具名挂载
匿名挂载
- -v 容器内路径
- 命令例子:docker run -d -P –name nginx01 -v /etc/nginx nginx
上面的命令就是匿名挂载,-v只写了容器内的路径,没有写容器外的路径
查看容器中数据卷的情况

具名挂载
- docker run -d -P –name nginx2 -v nginxTestFile:/etc/nginx nginx
通过 -v 卷名:容器内路径来实现具名挂载

所有的docker容器内的卷,没有指定目录的情况下都是在目录/var/lib/docker/volumes/xxxxx/_data
可以通过具名挂载方法方便找到一个卷,大多数情况都使用具名挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v 主机路径:容器内路径 # 指定路径挂载
拓展:
通过 -v 容器内路径:ro/rw 来改变读写权限
ro readonly 只读
rw readwrite 读写一旦设置了容器权限,容器对挂载出来的内容就存在限定。ro表示此路径只能通过宿主机来操作,容器内部是无法进行操作的。
docker run -d -P –name nginx01 -v nginx_1_file:/etc/nginx:ro nginx
docker run -d -P –name nginx02 -v nginx_2_file:/etc/nginx:rw nginx