当前位置: 首页 > news >正文

Docker基础知识教程(最详细最全)

Docker基础知识教程

Docker的历史

Docker的历史发展进程

Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。Docker 项目后来还加入了 Linux 基金会,并成立推动 开放容器联盟(OCI)。

Docker 自开源后受到广泛的关注和讨论,至今其 GitHub 项目已经超过 4 万 6 千个星标和一万多个 fork。甚至由于 Docker 项目的火爆,在 2013 年底,dotCloud 公司决定改名为 Docker。Docker 最初是在 Ubuntu 12.04 上开发实现的;Red Hat 则从 RHEL 6.5 开始对 Docker 进行支持;Google 也在其 PaaS 产品中广泛应用 Docker。

Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及AUFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的 libcontainer,从 1.11 开始,则进一步演进为使用 runC 和 containerd。

​ ----来自百度百科

⚠️ docker ≠ 虚拟化

⚠️ docker分为社区版和企业版(收费版),分别叫做docker-ce(社区版) docker-ee(企业版)

Docker 的安装

基于CentOS8-stream

# docker 的官方文档
https://docs.docker.com1. 开启centos-extra的仓库,默认是开启的
[root@localhost ~]# yum repolist2. 安装必要的一些系统工具
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm23. 添加docker的软件仓库(国外的)
[root@localhost ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo# 国内的仓库地址
[root@eleven yum.repos.d]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo5. 安装docker引擎
此时安装会报错,原因是docker-ce 里面的runc和podman底层的软件包在支持上冲突了,所以我们使用--allowerasing参数,替换掉冲突的软件包.
[root@localhost ~]# yum -y install docker-ce docker-ce-cli containerd.io --allowerasing
docker-ce: 这是 Docker 社区版(Community Edition)的主包,包含了 Docker 引擎。
docker-ce-cli: 这是 Docker 命令行客户端,允许你通过命令行与 Docker 交互。
containerd.io: 这是一个容器运行时,是 Docker 引擎的一个核心依赖项,用于管理和运行容器。6.下载完成后设置开机自启动和现在启动
[root@localhost ~]# systemctl enable docker --now
[root@localhost ~]# systemctl status docker7. docker hello world 测试
[root@localhost ~]# docker run hello-world

配置国内docker的镜像源

配置docker国内镜像源
使用docker拉取镜像的时候,有时候会卡在中途。一般这种情况就是因为docker默认的镜像源是Dockerhub,而这个网站在域外。所以我们可以对docker换国内镜像源。
常见的国内源有:Docker国内镜像源:https://registry.docker-cn.com
中科大源:https://docker.mirrors.ustc.edu.cn
网易源:https://hub-mirror.c.163.com
百度源:https://mirror.baidubce.com
腾讯源:https://ccr.ccs.tencentyun.com
阿里源:需要登陆 cr.console.aliyun.com   创建单独的镜像源链接,就不介绍了。docker的镜像源文件配置在 /etc/docker/daemon.json处,如果没有的话我们就创建一个然后再修改。
vim  /etc/docker/daemon.json
{"registry-mirrors": ["https://registry.docker-cn.com","https://docker.mirrors.ustc.edu.cn","https://hub-mirror.c.163.com","https://mirror.baidubce.com","https://ccr.ccs.tencentyun.com"]
}重启docker,由于走的是守护程序daemon,所以daemon进程也需要重启。
sudo systemctl daemon-reload		#重启daemon进程
sudo systemctl restart docker		#重启docker

docker info # 查看验证

如果在docker info 里看到下面这个信息,说明配置成功

Registry Mirrors:https://registry.docker-cn.com/https://docker.mirrors.ustc.edu.cn/https://hub-mirror.c.163.com/https://mirror.baidubce.com/https://ccr.ccs.tencentyun.com/
# 仓库配置
把默认的仓库都移动到新建的文件夹下,用国内的源
vim local.repo
[appstream]
name=CentOS Stream $releasever - AppStream
#mirrorlist=http://mirrorlist.centos.org/?release=$stream&arch=$basearch&repo=AppStream&infra=$infra
baseurl=https://mirrors.aliyun.com/$contentdir/$stream/AppStream/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial[baseos]
name=CentOS Stream $releasever - BaseOS
#mirrorlist=http://mirrorlist.centos.org/?release=$stream&arch=$basearch&repo=BaseOS&infra=$infra
baseurl=https://mirrors.aliyun.com/$contentdir/$stream/BaseOS/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial[extras]
name=CentOS Stream $releasever - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=$stream&arch=$basearch&repo=extras&infra=$infra
baseurl=https://mirrors.aliyun.com/$contentdir/$stream/extras/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial保存退出即可

对于拉取的镜像,都是经过压缩的,拉取的过程中会解压到本地

docker ps # 查看所有存活的容器docker ps -a # 查看所有的容器,包括已经停止的容器docker images # 查看所有本地的镜像docker container rm 容器ID # 删除停止的容器docker image rm 镜像ID  # 删除镜像

配置docker代理

有些情况下我们可能无法直接的访问到某些镜像仓库,但是有一个代理服务器可以访问到,那么如果我们想从
无法访问到的镜像仓库中拉取镜像,就需要配置docker的代理来访问到对应的镜像仓库来拉取镜像。
举例假设有一个代理服务器的环境,容器主机的地址是10.163.1.110,自己首先要有一个代理服务器地址和端口分别是
192.168.199.11:10808,但是注意,我这个代理服务器的协议是socks5。docker是没办法直接使用
socks5代理,所以我们需要将socks5代理转成http或者https,一般就是转换成http。1.将socks5的代理转换成http的代理
[root@localhost ~]# yum -y install epel-release
[root@localhost ~]# yum -y install privoxy
[root@localhost ~]# vim /etc/privoxy/config
[root@localhost ~]# egrep '^listen-address' /etc/privoxy/config -A 1
listen-address 0.0.0.0:8118
forward-socks5t / 192.168.199.11:10808 .
[root@localhost ~]# systemctl enable privoxy --now
[root@localhost ~]# netstat -tunlp | grep 8118
tcp 0 0 0.0.0.0:8118 0.0.0.0:* LISTEN
6172/privoxy2.配置docker使用http的代理
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo touch /etc/systemd/system/docker.service.d/proxy.conf
sudo chmod 777 /etc/systemd/system/docker.service.d/proxy.conf
sudo echo '
[Service]
Environment="HTTP_PROXY=http://10.163.1.110:8118"
Environment="HTTPS_PROXY=http://10.163.1.110:8118"
' >> /etc/systemd/system/docker.service.d/proxy.conf
sudo systemctl daemon-reload
sudo systemctl restart docker3.拉取镜像
关闭镜像加速器
[root@localhost ~]# mv /etc/docker/daemon.json /etc/docker/daemon.json.bak
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker
[root@localhost ~]# docker pull gcr.io/google-containers/ubuntu
Using default tag: latest
Error response from daemon: manifest for gcr.io/google-containers/ubuntu:latest
not found: manifest unknown: Failed to fetch "latest" from request "/v2/googlecontainers/
ubuntu/manifests/latest".[root@localhost ~]# docker pull gcr.io/google-containers/ubuntu:14.04
14.04: Pulling from google-containers/ubuntu
a3ed95caeb02: Pull complete
7059585c469e: Pull complete
782c76bb9e67: Pull complete
706514fbad74: Pull complete
Digest: sha256:5746b3b4974d1bd3d4ddbac0373fb71b425f13583797414ffd9d8b547d241f75
Status: Downloaded newer image for gcr.io/google-containers/ubuntu:14.04
gcr.io/google-containers/ubuntu:14.04[root@localhost ~]# docker pull ubuntu:xenial-20210114
xenial-20210114: Pulling from library/ubuntu
4007a89234b4: Pull complete
5dfa26c6b9c9: Pull complete
0ba7bf18aa40: Pull complete
4c6ec688ebe3: Pull complete
Digest: sha256:e74994b7a9ec8e2129cfc6a871f3236940006ed31091de355578492ed140a39c
Status: Downloaded newer image for ubuntu:xenial-20210114
docker.io/library/ubuntu:xenial-20210114[root@localhost ~]# docker pull docker.io/library/ubuntu:latest
latest: Pulling from library/ubuntu
83ee3a23efb7: Pull complete
db98fc6f11f0: Pull complete
f611acd52c6c: Pull complete
Digest: sha256:703218c0465075f4425e58fac086e09e1de5c340b12976ab9eb8ad26615c3715
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

docker镜像管理

1.Docker镜像拉取
docker pull命令就是默认拉取镜像的命令,默认情况下,如果不指定docker的仓库,默认的仓库就是从
dockerhub上拉取。如果指定了对应的docker仓库就从指定的仓库上拉取镜像。前提是没有配置镜像仓库的配置文件。从dockerhub上拉取镜像
[root@localhost ~]# docker pull ubuntu:xenial-20210114从gcr(google container registry)上拉取镜像
[root@localhost ~]# docker pull gcr.io/google-containers/ubuntu:14.042.Docker镜像的查看
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED  SIZE
ubuntu xenial-20210114 8185511cd5ad 2 days ago  132MB 
ubuntu latest f63181f19b2f 2 days ago  72.9MB3.Docker镜像删除
强烈不建议通过IMAGE ID删除镜像,有可能会出现误删除的情况,因为Docker存在repository和tag的概
念,有可能出现不同repository不同tag但是IMAGE ID是相同的情况,这样如果通过docker image rm命
令删除IMAGE ID,如果存在两个IMAGE ID相同,但是repository和tag不同的镜像就会出现一起删除的情
况。
#如果不指定tag,默认就会删除latest的
[root@localhost ~]# docker image rm REPOSITORY:TAG
[root@localhost ~]# docker image rm ubuntu:xenial-20210114
Untagged: ubuntu:xenial-20210114
Untagged:
ubuntu@sha256:e74994b7a9ec8e2129cfc6a871f3236940006ed31091de355578492ed140a39c
Deleted: sha256:8185511cd5ad68f14aee2bac83a449a6eea2be06f0a4715b008cfe19f07a64f7
Deleted: sha256:a6a3c16a476b20cd7548393454871276918f960d847eb55095d7a44baa5d26e0
Deleted: sha256:c43e1a302d470630ea24b649329b7e82933d368b822a47505b277aa5b468d6e3
Deleted: sha256:b3863b5a035a21534c3c0edf52fda7e157d1d2e0af84a39c94d796b6ecb2359a
Deleted: sha256:935c56d8b3f96d6587f3640e491767688b790c458a01fef327188abcbbafdc9a#如果已经有一个容器使用了你想要删除的镜像,那么你需要先删除这个容器,才能删除这个镜像
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS  PORTS NAMES
9974deece9ad hello-world "/hello" 2 hours ago Exited (0) 2 hours ago stupefied_hypatia
[root@localhost ~]# docker container rm 9974deece9ad
stupefied_hypatia
[root@localhost ~]# docker image rm hello-world4.Docker镜像导出
docker save
#-o参数表示输出为指定的文件
[root@localhost ~]# docker save ubuntu:latest -o ubuntu-latest.tar
[root@localhost ~]# ls -lh
total 72M
-rw-------. 1 root root 1.6K Nov 28 2019 anaconda-ks.cfg
-rw-------. 1 root root 72M Jan 24 01:55 ubuntu-latest.tar5.Docker镜像导入
docker load
#-i参数表示导入指定的文件
[root@localhost ~]# scp ubuntu-latest.tar 10.163.1.100:~/ubuntu-latest.tar
[root@stream ~]# docker load -i ubuntu-latest.tar
9f32931c9d28: Loading layer
[==================================================>] 75.27MB/75.27MB
dbf2c0f42a39: Loading layer
[==================================================>] 15.36kB/15.36kB
02473afd360b: Loading layer
[==================================================>] 3.072kB/3.072kB
Loaded image: ubuntu:latest
[root@stream ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest f63181f19b2f 2 days ago 72.9MB

在dockerhub上创建自己的仓库

首先,我们需要先理解docker的镜像仓库,docker镜像仓库的结构分为仓库本身,仓库里面的小仓库,还
有tag。我们来分析一下dockerhub的仓库构成。dockerhub的镜像仓库名称为docker.io,当我们想要从
dockerhub上拉取ubuntu镜像的时候,我们就从docker.io的大仓库中找到ubuntu这个小仓库,找到
ubuntu这个小仓库之后,我们需要指定我们要从ubuntu这个小仓库中拉取哪个tag(标记)个ubuntu镜像。#一般来说我们习惯将大仓库叫做docker registry,小仓库的名字叫做repository
1.在dockerhub上创建账号 hub.docker.com
2.在dockerhub登陆自己的账号并创建小仓库(repository)
https://hub.docker.com/repository-settings/default-privacy
在dockerhub上不花钱的情况下,只能创建一个私有仓库,但是公有仓库的数量则不作限制
公有仓库意味着你在这个仓库中的镜像都会被别人看到而且可以拉取。
你在私有仓库中上传的镜像不会被除了你之外的人看到。这里指的仓库是repository,并不是registry。

在这里插入图片描述

3.修改镜像的tag(看图)[root@localhost ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED       SIZE
centos        latest    5d0da3dc9764   3 years ago   231MB
hello-world   latest    48b5124b2768   7 years ago   1.84kB
[root@localhost ~]# docker tag centos:latest jinghong628/ztf:centos-latest
[root@localhost ~]# docker images
REPOSITORY        TAG             IMAGE ID       CREATED       SIZE
jinghong628/ztf   centos-latest   5d0da3dc9764   3 years ago   231MB
centos            latest          5d0da3dc9764   3 years ago   231MB
hello-world       latest          48b5124b2768   7 years ago   1.84kB4.使用自己的账号登陆到dockerhub并上传镜像到自己的小仓库
[root@localhost ~]# docker login
登录成功后上传镜像
[root@localhost ~]# docker push jinghong628/ztf:centos-latest

Docker容器

镜像是静态的,将镜像运行起来就是容器,所以说容器是动态的。镜像只会占用磁盘,但是容器会占用cpu,
内存和网络。
镜像的英文:image
容器的英文:container
注意:你不能将容器理解成一个操作系统,因为容器本身并不包含内核,没有内核的东西自然不能称为操作系统。
#docker run就是我们要运行容器时候的命令
[root@localhost ~]# docker run
[root@localhost ~]# docker container run
#早期就是用docker run来运行一个容器,但是在Docker后期版本对命令行进行更加明显的使用方法,docker image ...就表示操作docker镜像,docker container ...就表示操作容器
#docker run或者docker container run并不会直接运行一个容器,因为你缺少了运行容器所必须的条件。

运行容器

1. 一次性运行容器
#运行第一个容器
[root@localhost ~]# docker run centos
#需要注意的是如果docker run 后面指定的镜像没有加tag,那么默认就会运行tag为latest的镜像#查看运行的容器命令为docker ps
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 我们通过docker ps命令并没有查看到我们之前运行的基于centos:latest的容器。原因是什么呢?原因其实非常简单,
# 容器已经运行完毕了,运行完就自动退出了。我们可以使用docker ps -a查看所有的容器
#(包括运行结束退出的容器也可以查看到)这样一次性运行容器,没什么意义
2.交互式运行容器
#-i就表示交互的意思
#-t就表示tty,表示为容器开启一个终端[root@localhost ~]# docker run -it centos
# 我们通过pwd和ls命令查看到了,这个容器并没有/boot目录,原因也很好理解,因为容器不是操作系统,
所以不需要引导,也自然就没有内核存放的位置。[root@80e53ca247b4 /]# pwd
/
[root@80e53ca247b4 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run
sbin srv sys tmp usr var#容器内部的第一个进程/bin/bash
[root@80e53ca247b4 /]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 12132 3368 pts/0 Ss 13:24 0:00 /bin/bash
root 25 0.0 0.3 44636 3416 pts/0 R+ 13:28 0:00 ps aux# 退出容器
[root@80e53ca247b4 /]# exit
exit[root@80e53ca247b4 /]# exit
exit#由于我们在容器中使用exit命令退出了,就相当于退出了/bin/bash,也就意味着这个容器中唯一的进程被退出了,所以容器自然而然的就退出了。#容器所在主机的第一个进程/usr/lib/systemd/systemd
[root@localhost ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 1.3 178664 13424 ? Ss Jan24 0:06
/usr/lib/systemd/systemd --switched-root --system[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE         COMMAND       CREATED         STATUS                            PORTS     NAMES
e871f1ecd358   centos        "/bin/bash"   5 minutes ago   Exited (127) About a minute ago             busy_rubin
5852b7a34b40   centos        "/bin/bash"   8 minutes ago   Exited (0) 8 minutes ago               blissful_jones#如果你使用-i -t参数以交互式的形式运行了容器,那么你可以使用ctrl+p+q(按住ctrl,再按p,p松手,再按q)临时的退出容器,这个容器就并没有真正的被关闭。[root@localhost ~]# docker container run -it centos
[root@23aa64b0fe97 /]# [root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
23aa64b0fe97   centos    "/bin/bash"   19 seconds ago   Up 17 seconds             musing_yalow#当临时的退出容器,并不是exit退出的时候,可以使用docker attach命令,再回到容器
[root@localhost ~]# docker attach 23aa64b0fe97
3.以后台的形式运行容器(使用频率最高的)
#-d参数表示daemon的意思,表示将容器以守护进程的形式运行,说白了就是在后台运行。
[root@localhost ~]# docker run -d centos
b8a36e17766f93a2b6867a55ecc9cc488932f2ac55ce77caf2e76c471cc87a02# 那为什么在后台运行之后也是直接退出了呢?运行一次在前台退出和在后台退出是一样的。就好比运行一个
# ls命令一样,不管你是在前台运行还是在后台运行,都是运行完之后就退出。??????
#如何让一个容器在运行之后不退出呢?我们需要增加一个-t参数,-t参数的意思是开启一个终端。
#docker run "image" "command"后面的command会替代image构建的最后一个命令。[root@localhost ~]# docker run -td centos /bin/bash
8c615ee601bfa9ba6215d39ba6778ecca50d203d6f2dd7cba4f68b3db858f220#强烈不建议使用docker attach命令进入在后台运行的容器,建议使用docker exec加上对应参数进入后台运行的容器#docker exec表示容器的执行
# -i -t和docker run的参数是一样的 1facba8577ae表示的是容器的ID,bash表示以bash命令运行这个容器。[root@localhost ~]# docker exec -it 8c615ee601bf /bin/bash[root@1facba8577ae /]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 12028 3208 pts/0 Ss+ 13:42 0:00 /bin/bash
root 15 0.5 0.3 12028 3272 pts/1 Ss 13:47 0:00 bash
root 29 0.0 0.3 44636 3432 pts/1 R+ 13:47 0:00 ps aux
[root@1facba8577ae /]# exit
exit#因为你看上面的进程PID为1的进程为/bin/bash就是我在用docker run运行起来容器的那个进程,还有一
个PID为15的bash进程,是我用docker exec运行的进程,所以我使用exit并不是退出/bin/bash,而是
退出bash,所以由于容器里面的PID为1的进程/bin/bash还在,所以我exit之后没有退出容器,只是退出了
容器里面的一个bash而已。总结,当我们运行一个容器的同时,可以同时开启一个终端、后台运行。
说白了就是把上面的三个参数都加上。如下:
[root@localhost ~]# docker run -itd centos /bin/bash
7846c916a9896eb7b69e30a72293c7528877b6dc0e6b5510532f32703deaa447
然后docker ps 查看
然后使用docker exec 命令进入容器内部
docker exec -it 8c615ee601bf /bin/bash
4.容器的生命周期管理
1.容器的启动
docker run
docker container run2.容器的停止
[root@localhost ~]# docker stop 5bd5c48a9b21
[root@localhost ~]# docker start 5bd5c48a9b21
#没有加-d参数的容器,即使我们将它手工启动,也不会让他持续性运行
#只有以后台的形式运行的容器才有生命周期管理的意义#docker kill是强行干掉一个容器,docker stop是正常关闭一个容器3.容器的重启
[root@localhost ~]# docker restart 5b4a0e7710114.容器的删除
[root@localhost ~]# docker container rm 0caf099391e7
0caf099391e7
#默认情况下只能删除停止的容器,运行的容器删除会报错,但是也可以使用-f参数强行删除运行的容器(强烈不建议)
[root@localhost ~]# docker container rm 5b4a0e771011 -f
5b4a0e771011#容器查看的技巧
-q参数表示只查看容器的ID
[root@localhost ~]# docker ps -q
5bd5c48a9b21
41f5f33fb20b
1facba8577ae#docker ps -qa就是查看所有运行的或者终止的容器的ID
[root@localhost ~]# docker ps -qa
5bd5c48a9b21
41f5f33fb20b
1facba8577ae
79392e4ab5b1
41db22bcd9ed
80e53ca247b4#强行删除所有容器(仅限于lab环境操作)
[root@localhost ~]# docker rm -f `docker ps -qa`
5bd5c48a9b21
41f5f33fb20b
1facba8577ae
79392e4ab5b1
41db22bcd9ed
80e53ca247b4
5.查看容器信息
1.查看容器log
[root@localhost ~]# docker run -dt --name web nginx
[root@localhost ~]# docker logs web
2.查看容器进程信息
[root@localhost ~]# docker exec -it centos-test /bin/bash
[root@bf17d098af8b /]# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0  12052   108 pts/0    Ss+  13:44   0:00 /bin/bash
root          15  0.6  0.4  12052  3300 pts/1    Ss   13:50   0:00 /bin/bash
root          29  0.0  0.4  44668  3476 pts/1    R+   13:50   0:00 ps aux
#一般情况你可以进入到容器内部使用ps命令查看容器的进程信息,但并不是所有的容器都支持这么操作
例如这个nginx就没有这几个命令查看信息
[root@localhost ~]# docker exec -it web bash
root@cf839d63840e:/# ps aux
bash: ps: command not found
root@cf839d63840e:/# top
bash: top: command not found
root@cf839d63840e:/# exit
exit# 那我们就使用docker 自带的top命令查看进程信息
[root@localhost ~]# docker top web
3.查看容器内部细节
[root@localhost ~]# docker inspect web
这命令显示了这个容器的所有信息,返回的是一个json格式。
4.容器和主机间的文件拷贝
#将ubuntu-latest.tar拷贝到centos-test容器的根目录下
[root@localhost ~]# docker cp ./ubuntu-latest.tar centos-test:/
[root@localhost ~]# rm -rf ubuntu-latest.tar
[root@localhost ~]# docker cp centos-test:/ubuntu-latest.tar .
[root@localhost ~]# ls
anaconda-ks.cfg ubuntu-latest.tar

Docker容器的网络(重要)

当你使用容器时(以docker为例),容器的通信就变得至关重要。要解决容器的通信问题,必须具备一定的网
络基础。Docker有4种网络模式,只有两种是常用的。这4种网络模式分别为bridge,host,none,container。
常用的是host模式和bridge模式。

Docker的bridge 网络模式

docker安装后会创建一个docker0的网络模式(默认是bridge)
可以使用ifconfig命令看到docker0
[root@localhost ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500ether 02:42:09:21:9c:d6  txqueuelen 0  (Ethernet)RX packets 0  bytes 0 (0.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 26  bytes 2913 (2.8 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0在该模式中,Docker进程创建了一个以太网桥docker0,这个以太网桥你可以理解成一个交换机,
新建的容器默认会自动的桥接到这个网桥上#从RHEL8或者CentOS8开始已经默认不使用brctl命令查看网桥和网卡的关系了,代替的是bridge命令[root@localhost ~]# bridge link
8: veth1e09d15@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0
state forwarding priority 32 cost 2
10: veth73a6134@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master docker0
state forwarding priority 32 cost 2#在host上看到的两个桥接到docker网桥的网卡和容器内部看到的网卡并不是一个,因为mac地址不同。
#在host上看到的网卡和容器内部的网卡其实叫做veth pair
#veth pair其实是一对虚拟网卡,这一对虚拟网卡就像"网线"一样。# 查看docker的网络
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
c4ecebc40b67   bridge    bridge    local
03d74ff7daaa   host      host      local
46345571b473   none      null      local
总结:Docker的bridge网络模式的底层采用的是Linux bridge,veth pair,iptables

2.Docker的Host网络模式

Docker的Host网络模式其实就是容器和host共享一个网络。
说白了就是容器完全的使用容器所在主机上的网络,并不对容器网络做任何隔离。[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
3c53ba4dfbef bridge bridge local
23e291bc1ec1 host host local
bab83bfc1452 none null local#使用--network指定容器运行时的网络模式(默认的模式就是bridge模式)
[root@localhost ~]# docker run -dt --name centos1 --network host centos
c278f5ae3a05b4a014b4301a838d89217a746f806e2486d4a5a3ec2483109715#采用host网络模式的Docker容器,可以直接使用宿主机的IP地址与外界通信,若是宿主机的网络是一个公
#有IP,那么容器也会共享这个公有IP,同时容器服务的端口也可以使用宿主机的端口,无需进行SNAT的转
#换。
#带来的好处就是性能好,带来的劣势就是容器的网络缺少了隔离性,增加了风险,并且由于所有容器和宿
#主机共享同一个网络,网络资源也受到了限制。

3.Docker的none网络模式

none的网络模式是Docker容器中最容易理解的一种网络模式,因为如果使用了none作为Docker容器的网络
模式,那么就意味着容器会禁用网络功能,只会留一个环回接口。
我们同样可以使用--network参数在容器运行的时候指定none类型的网络。[root@localhost ~]# docker run -itd --name centos1 --network none centos
9f8e65b539aa98a97acbc40be2846aa1a3d98b9ff48ac080dcfb0fe7a32c0ecd# 可以看到,只有一个环回网络loopback
[root@localhost ~]# docker exec -it centos1 ip add show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forevernone模式的好处就是Docker容器几乎不参与网络的配置,那么如果你想针对这个容器配置网络,就需要第三
方的driver。none模式的优点就是让你容器的网络设置更加的开放,不再局限于Docker自带的网络模式。

4.Docker的container网络模式

container类型的网络表明指定一个容器,和那个容器共享一个网络
# 这个网络模式用的很少
# 让centos3和centos1共享一个网络
[root@localhost ~]# docker run -dt --network container:centos1 --name centos3 centos

5.Docker自定义网络和网络连接

通过我们之前的学习,我们知道了,Docker容器网络的几种常见的模式。
默认情况下docker容器会使用bridge类型的网络。# 创建自定义的网络
docker network create [网络名字] 
[root@localhost ~]# docker network create test-network
2918b30dd25a9406a8fa4ce4e2885f718d1e6753da3ea792b17a0572aa03d775
#这里我创建了一个名为 test-network的网络可以用ip add show 看到这个网络
[root@localhost ~]# ip add show
31: br-2918b30dd25a: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:7b:61:4d:31 brd ff:ff:ff:ff:ff:ffinet 172.18.0.1/16 brd 172.18.255.255 scope global br-2918b30dd25avalid_lft forever preferred_lft forever# 可以看到这个网络的Ip地址范围是 172.18.0.1/16# 运行一个容器并且使用我们刚才创建的网络(说白了就类似于添加了一个虚拟网卡一样)
# 为了清理环境,我把之前的运行的和未运行的容器全部停掉都删掉了。这样做也是保证一个干净的环境
[root@localhost ~]# docker stop `docker ps -q` # 停掉容器
[root@localhost ~]# docker container rm `docker ps -aq`  # 删除已停止的容器# 运行一个容器,使用刚才自定义的网络
[root@localhost ~]# docker run -itd --name centos1 --network test-network centos
458674cdbe0e4c1082e6351e7ab4ca92ab04e0a142ebebcd890bfc6873c7f125# 查看这个容器分配的地址
[root@localhost ~]# docker exec -it centos1 ip a
32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0valid_lft forever preferred_lft forever

断开容器的网络连接

刚才是给容器连接上自定义的网络,我们也可以让这个网络与容器断开连接
[root@localhost ~]# docker network disconnect test-network centos1
[root@localhost ~]# docker exec -it centos1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
再次查看centos1网络可以看到,已经没有分配地址了,说明我们成功的断开连接了

连接容器的网络

我们再给容器把网络连接上
[root@localhost ~]# docker network connect test-network centos1
[root@localhost ~]# docker exec -it centos1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
34: eth1@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1valid_lft forever preferred_lft forever# 可以看到,ip地址已分配,我们成功的连接了网络

注意:如果你想删除一个网络,那么必须要先将这个网络中的容器断连,全部断连之后,你才能删除这个网络

使用 docker network rm [网络名字] 删除网络

有没有发现,其实创建一个网络,其实就跟添加一块虚拟网卡一样的效果

给容器连接网络,就是给机器插上网卡,断开,就是拔掉网卡

6.Docker容器间网络通信

Docker网络设置的目的无非就是两个,第一个要保证容器间的通信,第二要保证外部能够访问到我们的容器承载的业务。
比如说我们有一些复杂的应用,要部署在不同的容器中,那么我们为了让着个复杂的应用能够完美运行,
我们一般都要求不同容器的端口实现通信。想实现容器之间的通信,有两种方法,第一种就是将容器放到同一个bridge中,第二种就是将容器都设置为host的网络模式,让容器和宿主机共享一个网络#比如我们运行两个容器,用其中一个容器去ping另外的容器地址(猜猜看通不通)
[root@localhost ~]# docker run -dt --name centos2 centos
cc57dbcc0497e394dd65f00ff8e9e507f641b6df316be92c1b80438d1ddee5ed
[root@localhost ~]# docker run -dt --name centos3 centos
5c3995b00ed93d56a0f223d8d2976c16041d6983eadc18681ec956c962f51a0d
# 查看两个容器的IP
[root@localhost ~]# docker exec -it centos2 ip a   # 它的是172.18.0.3[root@localhost ~]# docker exec -it centos3 ip a    # 它的是172.18.0.4[root@localhost ~]# docker exec -it centos2 ping -c 1 172.17.0.4
# 结果就是【通的】这两个容器在一个网络中,容器之间网络是通的

7.Docker容器被外部访问

Docker容器被外部访问一般基于两种网络模式,第一种是bridge,第二种是Host。
如果是bridge模式则需要通过DNAT的方法让我们的Docker容器被访问到
如果是Host模式,则我们的Docker容器可以直接被访问到[root@localhost ~]# docker run -dt --name gzy-web1 nginx
a8377054e8eadbfbc248b40a769a426c4c8db2bbac2145611a9be9af64b46aa9#上面的情况默认外部是访问不到nginx容器的,因为nginx容器所获得的地址是docker网桥内部的地址。# 如果想外部访问到容器,就需要做端口映射,使用-p参数
#这里是指将宿主机的8080端口映射到容器的80端口
[root@localhost ~]# docker run -dt --name gzy-web2 -p 8080:80 nginx
992ef3c54a8098df9f578c9cae819d0d76be8cafef9f08101c96389d43665604# 使用docker ps 可以看到 多了一个端口映射的内容
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS   PORTS NAMES
992ef3c54a80 nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds  0.0.0.0:8080->80/tcp gzy-web2# 使用curl命令就可以访问到nginx的欢迎页面
[root@localhost ~]# curl localhost:8080
如果容器的网络模式是host,那就简单了,由于容器会和host共享一个网络,那么容器曝露的端口将会被直接访问到
root@localhost ~]# docker run -dt --network host --name gzy-web3 nginx
9ab4fb74e1fa3fcaedbc0467304cc9f3b70d50518e35dc5d836a7c3f629ce783# 我们可以通过netstate命令看到本机已经自动监听了80端口
# 现在你可以通过浏览器访问到nginx的欢迎页面(记得关闭防火墙或者放行80端口)
[root@localhost ~]# netstat -tunlp
[root@localhost ~]# curl localhost# 疑惑?
那为啥上面-p参数那块不用关闭防火墙或者放行端口就可以直接在浏览器访问到呢?
很简单,当我们嫩使用-p参数执行后,docker自动帮我们做了防火墙的端口放行。所以自然能访问。

Docker容器的持久化存储

1.Docker镜像的分层

Docker容器和Docker镜像的关系。
Docker镜像运行之后就是Docker容器。(通俗的解释)
基于Docker镜像挂载一个可读可写的文件系统,这个文件系统就是Docker容器的根分区。有了根分区,我们
才能认为Docker容器像一个操作系统,可以运行。Docker镜像本身是没有写权限的。基于Docker镜像之上挂载一个可读可写的文件系统就可以当这个文件系统
是一个Docker容器的文件系统。
也就是说我们针对Docker容器的操作,其实是我们在可读可写的文件系统上操作,而不是操作Docker容器底
层的镜像。因为Docker镜像是不具备写权限的。所以无论你在Docker容器内做任何操作都不会影响到Docker镜像。为何Docker容器的存储是非持久化的?
因为Docker容器的文件系统是即用即删的。也就意味着,当你的Docker容器被删除之后,你挂载的Docker
文件系统也会被删除,那么你在Docker容器中做的任何操作,都会随着Docker容器的文件系统删除而删除。

在这里插入图片描述

2.Docker容器使数据卷Volume

#如果想让容器实现持久化存储,那么可以使用data volume来实现。
#data volume叫做数据卷,我们可以将数据库挂载到容器当中,进而让存储在数据卷中的数据不会随着容器的删除而删除。#默认情况下,没有任何的volume
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME#/var/lib/docker/volume是存储本地volume的默认路径,所以说我们创建的volume默认都存放在这个位置
[root@localhost ~]# ls /var/lib/docker/volumes/
backingFsBlockDev  metadata.db# 接下来我们创建一个volume 
[root@localhost ~]# docker volume create ztf
ztf
# 然后我们就能在/var/lib/docker/volumes/下看到刚才创建的volume
[root@localhost ~]# ls /var/lib/docker/volumes/
backingFsBlockDev  metadata.db  ztf# 创建的volume下的_data目录就是真正存放数据的地方。
[root@localhost ~]# ls /var/lib/docker/volumes/ztf/_data/# 用df -Th命令查看这个目录,其实可以明确的发现,这个卷目录其实就是宿主机的根。
[root@localhost ~]# df -Th /var/lib/docker/volumes/ztf/
Filesystem          Type  Size  Used Avail Use% Mounted on
/dev/mapper/cs-root xfs    17G  7.2G  9.9G  42% /# 接着我们运行一个容器并且使用刚才创建的volume
# -v 是指定容器运行时的卷,这个卷需要挂载点,我们将ztf卷挂在在容器根目录下的ztf目录下。
-v ztf:/ztf # 注意:第一个ztf是创建的卷  第二个/ztf是容器里的挂载点。
[root@localhost ~]# docker run -itd --name centos1 -v ztf:/ztf centos 
1f8d3aeba752114758f49977e3295d9d3ce82f12d68f13fa478656fafb0617ce# 我们进入容器,并在ztf目录下创建一个test文件
[root@localhost ~]# docker exec -it centos1 /bin/bash
[root@1f8d3aeba752 /]# cd ztf/
[root@1f8d3aeba752 ztf]# touch test
[root@1f8d3aeba752 ztf]# ls
test# 退出容器并在我们宿主机上的/var/lib/docker/volumes/ztf/_data目录下查看是否该文件存在
[root@1f8d3aeba752 ztf]# exit
exit
[root@localhost ~]# ls /var/lib/docker/volumes/ztf/_data/
test
# 可以看到,文件存在
# 通过上面的操作,我们可以看到在容器的/ztf目录下创建的文件都会被映射到/var/lib/docker/volumes/ztf/_data这个目录中。# 现在我们删除这个centos1容器,看看宿主机上的文件是否会被删除
[root@localhost ~]# docker stop centos1 
[root@localhost ~]# docker rm centos1 
[root@localhost ~]# ls /var/lib/docker/volumes/ztf/_data/
test
# 可以看到,数据依旧存在,这样我们就实现了Docker容器的数据存储持久化!!!!!
# 即使容器被删除,数据也不会被删除。
#我们之前的步骤是先创建volume,再挂载数据卷
#我们现在换一种方法使用数据卷
[root@localhost ~]# docker run -dt --name goudan2 -v ztf2 centos
b3caa31a5c0e125da66a8664f6e1d4e119ff95adc10af3b66b9720f5cc9b2cc8[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local 38f1f89f1f51a00a0a807d779774d8dbfe171549038ebfb929f7c0c7a62dc7e5
local ztf如果创建容器的时候不使用-v参数的标准格式来使用数据卷,那么docker会自动帮你创建一个数据卷,并且数据卷名字是随机的。
如果以上面的例子来看,那么ztf2并不是任何的数据卷,而是挂载点,而且是/ztf2
# 以上方式并不推荐xxxxxxxxxx
推荐指数 一颗星🌟
# 这时候,最终的最推荐的方式是这样的
[root@localhost ~]# docker run -dt --name goudan3 -v web:/web nginx
bc5cf0574ef0cdf00f238fba85ba8cd43ba1f3d1519a12518784830dab6f4012
[root@localhost ~]# docker volume ls
DRIVER VOLUME NAME
local web#我们在运行容器的时候,使用-v参数直接指定数据卷和挂载点,docker会自动帮你创建对应的数据卷和挂载点目录
推荐指数 三颗星🌟🌟🌟

3.Docker容器使用bind mounts

# 容器的bind mounts相比于容器的数据卷来说,使用上更加的灵活。
# 因为容器的数据卷存储位置是固定的,且是为docker存储所纳管的(docker volume ls查出来的就是docker 纳管的数据卷)
# 现在大部分公司企业都是使用的bind mounts这种方式来创建数据卷,它不受docker的约束,更加灵活,与docker是不同的,分开的。# 做个实验就明白了
# 1 创建一个目录。比如在/mnt下创建bind目录
[root@localhost ~]# mkdir /mnt/bind# 2. 将/mnt/bind挂载到容器里
[root@localhost ~]# docker run -itd --name centos2 -v /mnt/bind:/bind centos
e438a911053c20f22e0cd748aa09db18ce48e20d2ee8457aca76e4e413bd269e
# 这里其实和上面我们说的一模一样,不一样的地方只在于我们自定义了数据存放的目录,这样更加灵活,且不受docker纳管。
# 用docker volume ls 也是看不到这个数据卷的,已经不受docker纳管了。仅仅只是和容器的挂载点的目录进行一个简单的映射而已。
[root@localhost ~]# docker volume ls
DRIVER    VOLUME NAME
local     ztf# 效果同我们讲的第一种是一样的,也是实现了数据的持久化存储。
# 你可以做实验去验证即可。[root@localhost ~]# docker exec -it centos2 /bin/bash
[root@e438a911053c /]# ls
bin  bind  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var# 通常推荐使用这种方式来挂在数据卷。推荐指数 五颗星🌟🌟🌟🌟🌟

5.Docker容器的自启动策略

docker容器默认情况下,如果宿主机关机再开机之后,docker容器将不会自动启动。
1.我们必须要确保容器的服务是开机自启动的
[root@localhost ~]# systemctl enable docker --now2.我们必须要确保哪些容器需要开机自启动# 加上 restart=always参数
[root@localhost web]# docker run -itd -p 81:80 -v /opt/web/:/usr/local/apache2/htdocs --name web1 --restart=always httpd
4cfb7e35ff7954a9ba271826d47a56334339c23a58aa24d851e4295f0681f59a# 当你重启宿主机,容器会自启动
docker logs web1  # 查看容器的日志#--restart参数有三个
默认是no,表示容器退出时,不重启容器
on-failure表示只有容器在非0状态退出时才重新启动容器
always表示无论任何状态退付出,都重启容器

练习题

认真学完上述内容,请以所学内容完成以下几个任务!

  • 配置docker的国内镜像源,并成功拉取最新的httpd镜像

  • 运行httpd镜像成为容器,指定名字为web1 ,并映射宿主机88端口到容器80端口,并成功访问

  • 运行httpd镜像成为容器,指定名字为web2,并指定网络模式为【主机模式】,且实现数据持久化存储和开机自启动,且创建index.html,写入 “hello-world” ,并成功在页面访问到。

  • 以正常步骤停止容器并删除所有容器


http://www.mrgr.cn/news/56438.html

相关文章:

  • C++类和对象 - 下【匿名对象,友元,static成员】
  • 24最新Stable Diffusion 入门教程开篇!
  • golang的数组、slice和map
  • Unity学习记录-API
  • 免费开源的微信开发框架
  • 【The Art of Unit Testing 3_自学笔记02】第二章:编写第一个单元测试(上)
  • Android 拦截第三方推送的通知消息或系统消息或通知栏
  • 【C++、数据结构】二叉排序树(二叉查找树、二叉搜索树)(图解+完整代码)
  • C++入门知识
  • 【二刷hot100】day 4
  • Python程序设计 内置模块 随机函数
  • 【C++】— 一篇文章让你认识STL
  • Git的原理和使用(六)
  • 开源医疗管理的未来:参与码良诊所管理系统,助力智能医疗
  • 中国古代数学的杰出研究成果之一 - 杨辉三角 - 怎么用go、C++进行编程解决
  • 二叉树展开为链表
  • 代码随想录算法训练营第51天|101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104.建造最大岛屿
  • 集合框架16:HashMap的使用
  • C++编程语言:抽象机制:特殊运算符(Bjarne Stroustrup)
  • 容灾与云计算概念
  • Javascript基础面试题
  • Leetcode—1114. 按序打印【简单】(多线程)
  • http作业
  • 10.22软考初级网络管理员工重点之因特网与网络互联技术
  • 红黑树(创建 插入 测试验证)
  • 深入了解Java