Docker

第一部分 Docker快速入门

centos下载

http://mirrors.aliyun.com/centos/7/isos/x86_64/

配置阿里云yum源

1.下载安装wget
yum install -y wget

2.备份默认的yum
mv /etc/yum.repos.d /etc/yum.repos.d.backup

3.设置新的yum目录
mkdir -p /etc/yum.repos.d

4.下载阿里yum配置到该目录中,选择对应版本
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

5.更新epel源为阿里云epel源
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

6.重建缓存
yum clean all
yum makecache

7.看一下yum仓库有多少包
yum repolist

升级系统内核

rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm

yum --enablerepo=elrepo-kernel install -y kernel-lt
grep initrd16 /boot/grub2/grub.cfg

grub2-set-default 0

reboot

查看centos系统内核命令:
uname -r
uname -a

关闭防火墙

systemctl stop firewalld
systemctl disable firewalld

关闭selinux

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux

setenforce 0

网桥过滤

vi /etc/sysctl.conf

net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-arptables = 1
net.ipv4.ip_forward=1
net.ipv4.ip_forward_use_pmtu = 0

生效命令
sysctl --system

命令补全

安装bash-completion
yum -y install bash-completion bash-completion-extras

使用bash-completion
source /etc/profile.d/bash_completion.sh

安装docker

https://www.docker.com
https://docs.docker.com/
https://github.com/docker/docker-ce

安装docker前置条件

yum install -y yum-utils device-mapper-persistent-data lvm2

添加源

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum makecache fast

查看docker版本

yum list docker-ce --showduplicates | sort -r

安装docker

安装最新版:
yum -y install docker-ce

安装指定版本:
语法规则:yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING>
containerd.io
yum install -y docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7

开启docker服务

systemctl start docker

systemctl status docker

systemctl enable docker

安装镜像加速器

mkdir -p /etc/docker

tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https:加速器地址"]
}
EOF

systemctl daemon-reload

systemctl restart docker

docker命令

docker -v
docker version
docker info

docker命令分类

根据 docker官网案例,总的来说分为以下几种:

  • Docker环境信息 — docker [info|version]
  • 容器生命周期管理 — docker [create|exec|run|start|stop|restart|kill|rm|pause|unpause]
  • 容器操作管理 — docker [ps|inspect|top|attach|wait|export|port|rename|stat]
  • 容器rootfs命令 — docker [commit|cp|diff]
  • 镜像仓库 — docker [login|pull|push|search]
  • 本地镜像管理 — docker [build|images|rmi|tag|save|import|load]
  • 容器资源管理 — docker [volume|network]
  • 系统日志信息 — docker [events|history|logs]

官网地址

https://docs.docker.com/engine/reference/run/

从docker命令使用出发,梳理出如下命令结构图:
Docker_第1张图片

Docker镜像(image)

https://hub.docker.com/
http://hub.daocloud.io/

首先需要先从镜像仓库服务中拉取镜像。常见的镜像仓库服务是 Docker Hub,拉取操作会将镜像下载到本地 Docker 主机,可以使用该镜像启动一个或者多个容器。 镜像由多个层组成,每层叠加之后,从外部看来就如一个独立的对象。镜像内部是一个精简的操作系统 (OS),同时还包含应用运行所必须的文件和依赖包。镜像可以理解为一种构建时(build-time)结构,而容器可以理解为一种运行时(runtime)结构

镜像常用命令

pull命令

常用参数

  • -a, --all-tags=true|false : 是否获取仓库中所有镜像,默认为否;
  • –disable-content-trust : 跳过镜像内容的校验,默认为 true;
docker pull tomcat:9.0.20-jre8
docker pull tomcat:9.0.20-jre8-slim
docker pull tomcat:9.0.20-jre8-alpine

如果多个不同的镜像中,同时包含了同一个层,Docker 在下载之前,会去检测本地是否会有同样 ID 的层,如果本地已经存在了,就直接使用本地的就好了。

images命令

通过使用如下两个命令,列出本机已有的镜像:

docker images
docker image ls
save命令

一个镜像

docker save tomcat:9.0.20-jre8-alpine -o tomcat9.tar
docker save tomcat:9.0.20-jre8-slim > tomcat9.slim.tar
常用参数
-o :输出到的文件

多个镜像

docker save \
tomcat:9.0.20-jre8-alpine \
tomcat:9.0.20-jre8-slim \
tomcat:9.0.20-jre8 \
-o tomcat9.0.20.tar
load命令
docker load -i linux.tar
docker load < tomcat9.0.20.tar
常用参数
--input , -i : 指定导入的文件。
--quiet , -q : 精简输出信息。
inspect命令

通过 docker inspect 命令,我们可以获取镜像的详细信息,其中,包括创建者,各层的数字摘要 等。docker inspect 返回的是 JSON格式的信息,如果想获取其中指定的一项内容,可以通过 -f 来指 定,如获取镜像大小

docker inspect tomcat:9.0.20-jre8-alpine
docker inspect -f {{".Size"}} tomcat:9.0.20-jre8-alpine
history命令

通过 docker history命令,可以列出各个层的创建信息

docker history tomcat:9.0.20-jre8-alpine
tag命令

标记本地镜像,将其归入某一仓库。

docker tag tomcat:9.0.20-jre8-alpine l/tomcat:9
rmi命令

通过如下两个都可以删除镜像:

docker rmi tomcat:9.0.20-jre8-alpine
docker image rm tomcat:9.0.20-jre8-alpine
常用参数
-f, -force : 强制删除镜像,即便有容器引用该镜像;
-no-prune : 不要删除未带标签的父镜像;
清理镜像

使用 Docker 一段时间后,系统一般都会残存一些临时的、没有被使用的镜像文件,可以通过以 下命令进行清理。执行完命令后,还是告诉我们释放了多少存储空间

docker image prune
常用参数
-a, --all : 删除所有没有用的镜像,而不仅仅是临时文件;
-f, --force :强制删除镜像文件,无需弹出提示确认;

Docker容器(container)

容器是镜像的运行时实例。正如从虚拟机模板上启动 VM 一样,用户也同样可以从单个镜像上启动一个 或多个容器。虚拟机和容器最大的区别是容器更快并且更轻量级——与虚拟机运行在完整的操作系统之 上相比,容器会共享其所在主机的操作系统/内核。

Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。

容器是镜像的一个运行实例。可以将其启动、开始、停止、删除,而这些容器都是彼此相互隔离的、互不可见的。 可以把容器看做是一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间 等)以及运行在其中的应用程序打包而成的盒子。

容器是基于镜像启动起来的,容 器中可以运行一个或多个进程。

镜像是Docker生命周期中的构建或打包阶段,而容器则是启动或执行阶段。 镜像自身是只读的。容器从镜像启动的时候,会在镜像的最上层创建一个可写层。

容器常用命令

新建并启动容器

语法

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

常用参数

  • -d, --detach=false: 后台运行容器,并返回容器ID
  • -i, --interactive=false: 以交互模式运行容器,通常与 -t 同时使用
  • -p, --publish=[]: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t, --tty=false: 为容器重新分配一个伪输入终端,通常与 -i 同时使用
  • –name=“nginx-lb”: 为容器指定一个名称
  • -h , --hostname=“laosiji”: 指定容器的hostname
  • -e , --env=[]: 设置环境变量,容器中可以使用该环境变量
  • –net=“bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型
  • –link=[]: 添加链接到另一个容器;不推荐使用该参数
  • -v, --volume : 绑定一个卷
  • –privileged=false: 指定容器是否为特权容器,特权容器拥有所有的capabilities
  • –restart=no:指定容器停止后的重启策略 no:容器退出时不重启 ;on-failure:容器故障退出(返回值非零)时重启 ; always:容器退出时总是重启,推荐使用
  • –rm=false: 指定容器停止后自动删除容器,不能以docker run -d启动的容器

运行容器

docker run -it --rm -p 8080:8080 tomcat:9.0.20-jre8-alpine
容器日志

语法

docker logs [OPTIONS] CONTAINER
docker run -itd --name tomcat9 -p 8080:8080 tomcat:9.0.20-jre8-alpine
docker logs -f tomcat9

常用参数
-f : 跟踪日志输出
--tail :仅列出最新N条容器日志
删除容器
docker run -itd --name tomcat9 -p 8080:8080 tomcat:9.0.20-jre8-alpine
需要先停止运行中的容器再删除,否则无法删除容器
docker stop tomcat9
按照容器名称删除
docker rm tomcat9
按照容器ID删除
docker rm 7dh96p98e627

常用参数
-f :通过 SIGKILL 信号强制删除一个运行中的容器。
-l :移除容器间的网络连接,而非容器本身。
-v :删除与容器关联的卷。
列出容器
docker ps [OPTIONS]
常用参数
-a :显示所有的容器,包括未运行的。
-q :只显示容器编号。
docker run -itd --name tomcat9 -p 8080:8080 tomcat:9.0.20-jre8-alpine
查看运行中的容器
docker ps tomcat9
查看所有容器
docker ps -a tomcat9

输出详情介绍:

  • CONTAINER ID: 容器 ID。
  • IMAGE: 使用的镜像。
  • COMMAND: 启动容器时运行的命令。
  • CREATED: 容器的创建时间。
  • STATUS: 容器状态。 状态有7种: created(已创建) 、restarting(重启中) 、running(运行中)、removing(迁移中) 、paused(暂停) 、exited(停止) 、dead(死亡)
  • PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。
  • NAMES: 自动分配的容器名称。
启动、重启、终止容器

docker start :启动一个或多个已经被停止的容器

docker stop :停止一个运行中的容器

docker restart :重启容器

docker start [OPTIONS] CONTAINER [CONTAINER...]
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker restart [OPTIONS] CONTAINER [CONTAINER...]
实用技巧
停止所有运行容器
docker stop $(docker ps -qa)

删除所有的容器
docker rm $(docker ps -aq)
docker rm $(docker stop $(docker ps -q))

删除所有的镜像
docker rmi $(docker images -q)
进入容器
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

有bash命令的linux系统:例如centos
docker run -it --name tomcat9.1 -p 8080:8080 tomcat:9.0.20-jre8-slim
docker exec -it tomcat9.1 /bin/bash

没有bash命令的linux系统:例如alpine系统
docker run -it --name tomcat9.2 -p 8081:8080 tomcat:9.0.20-jre8-alpine
docker exec -it tomcat9.2 sh

常用参数
-i :即使没有附加也保持STDIN 打开
-t :分配一个伪终端
查看容器
docker inspect [OPTIONS] NAME|ID [NAME|ID...]

docker run -it --name tomcat9 -p 8081:8080 tomcat:9.0.20-jre8-alpine
docker inspect tomcat9

常用参数
-f :指定返回值的模板文件。
-s :显示总的文件大小。
--type :为指定类型返回JSON。
杀掉容器
docker kill [OPTIONS] CONTAINER [CONTAINER...]

docker run -it --name tomcat9 -p 8081:8080 tomcat:9.0.20-jre8-alpine
docker kill tomcat9
docker ps
docker ps -a
docker start tomcat9

安装mysql

https://hub.docker.com/_/mysql

拉取镜像
docker pull mysql:5.7.31
备份镜像
docker save mysql:5.7.31 -o mysql.5.7.31.tar
导入镜像
docker load -i mysql.5.7.31.tar

运行mysql

docker run -itd --name mysql --restart always --privileged=true -p 3306:3306 -e MYSQL_ROOT_PASSWORD=admin mysql:5.7.31 --character-set-server=utf8 --collation-server=utf8_general_c

-e , --env=[]: 设置环境变量,容器中可以使用该环境变量
特权模式

–privileged 可以不受限制地访问任何自己的系统调用。在正常的操作中,即使容器内有 root, Docker 也会限制容器的 Linux Capabilities 的,这种限制包括像 CAP_AUDIT_WRITE 这样的东西,它允 许覆盖内核的审计日志–你的容器化工作负载很可能不需要这个 Capabilities。所以特权只应该在你真正 需要它的特定设置中使用,简而言之,它给容器提供了几乎所有主机(作为root)可以做的事情的权 限。

本质上,它就是一个免费的通行证,可以逃避容器所包含的文件系统、进程、sockets 套接字等,当然 它有特定的使用场景,比如在很多 CI/CD 系统中需要的 Docker IN Docker 模式(在 Docker 容器内部 需要 Docker 守护进程),以及需要极端网络的地方。

第二部分 Docker核心原理

docker网络

docker安装后会自动创建3种网络:bridge、 host、 none

docker network ls

docker使用Linux桥接网卡,在宿主机虚拟一个docker容器网桥(docker0),docker启动一个容器时会根 据docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时docker网桥是每个容器的默认网 关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接 通信。

docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着 外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容 器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时 候就通过[宿主机IP]:[容器端口]访问容器。

网络模式

Docker_第2张图片

bridge模式

默认的网络模式。bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的,但容器通过宿主机的NAT规则后可以访问外网。

Bridge 桥接模式的实现步骤主要如下:

  • Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和 veth1。而veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另 一方。
  • Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0网桥上。保证宿主机的网络报文可以发往 veth0;
  • Docker Daemon 将 veth1 添加到Docker Container 所属的 namespace 下,并被改名为eth0。 如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到Docker Container网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。

Bridge桥接模式的缺陷:

  • 最明显的是,该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网 段。导致的结果是宿主机以外的世界不能直接和容器进行通信。
  • 虽然 NAT 模式经过中间处理实现了这一点,但是 NAT 模式仍然存在问题与不便,如:容器均需要在 宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等。另外 NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。

注意:veth设备是成双成对出现的,一端是容器内部命名为eth0,一端是加入到网桥并命名的veth(通常命名 为veth),它们组成了一个数据传输通道,一端进一端出,veth设备连接了两个网络设备并实现了数据通信

host模式

相当于Vmware中的NAT模式,与宿主机在同一个网络中,但没有独立IP地址。

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是 和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿 主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机 的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就 不能再用了,网络的隔离性不好。

host网络模式需要在容器创建时指定–network=host

host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用宿主机 的 IP地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有IP。同时容器内 服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。

host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

Host 网络模式的缺陷:

最明显的是 Docker Container 网络环境隔离性的弱化。即容器不再拥有隔离、独立的网络环境。 另外,使用 host 模式的 Docker Container 虽然可以让容器内部的服务和传统情况无差别、无改造的使 用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用; 另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有 部分端口已经用以 bridge 网络模式容器的端口映射。

Container网络模式

一种特殊host 网络模式

Container 网络模式是 Docker 中一种较为特别的网络的模式。在容器创建时使用–network=container:vm1指定。(vm1指定的是运行的容器名)

处于这个模式下的 Docker 容器会共享一个网络环境,这样两个容器之间可以使用localhost高效快速通信。

缺陷:它并没有改善容器与宿主机以外世界通信的情况(和桥接模式一样,不能连接宿主机以外的其他设备)

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。 同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网 卡、配置IP等。

这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

overlay 网络模式

Overlay 网络,也称为覆盖网络。主要用于docker集群部署。 Overlay 网络的实现方式和方案有多种。Docker自身集成了一种,基于VXLAN隧道技术实现。 Overlay 网络主要用于实现跨主机容器之间的通信。

应用场景:需要管理成百上千个跨主机的容器集群的网络时

macvlan 网络模式

macvlan网络模式,最主要的特征就是他们的通信会直接基于mac地址进行转发。

这时宿主机其实充当一个二层交换机。Docker会维护着一个MAC地址表,当宿主机网络收到一个数据包 后,直接根据mac地址找到对应的容器,再把数据交给对应的容器。

容器之间可以直接通过IP互通,通过宿主机上内建的虚拟网络设备(创建macvlan网络时自动创建), 但与主机无法直接利用IP互通。

应用场景:由于每个外来的数据包的目的mac地址就是容器的mac地址,这时每个容器对于外面网络来 说就相当于一个真实的物理网络设备。因此当需要让容器来的网络看起来是一个真实的物理机时,使用 macvlan模式

bridge网络

bridge网络表现形式就是docker0这个网络接口。容器默认都是通过 docker0这个接口进行通信。也可以通过docker0去和本机的以太网接口连接,这样容器内部才能访问互联网。

查看docker0网络,在默认环境中,一个名为docker0的linux bridge自动被创建好了,其上有一个
docker0 内部接口,IP地址为172.17.0.1/16
ip a

查看docker 网络
docker network ls

查看bridge网络详情。主要关注Containers节点信息。
docker network inspect bridge

docker0详解

Docker 创建一个容器的时候,会执行如下操作:

  • 创建一对虚拟接口/网卡,也就是veth pair,分别放到本地主机和新容器中;
  • 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字
  • 容器一端放到新容器中,并修改名字作为 eth0,这个网卡/接口只在容器的名字空间可见;
  • 从网桥可用地址段中(也就是与该bridge对应的network)获取一个空闲地址分配给容器的 eth0,并配置默认路由到桥接网卡 。

完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。 如果不指定–network,创建的容器默认都会挂到 docker0 上,使用本地主机上 docker0 接口的 IP 作为所有容器的默认网关。

Docker_第3张图片

link容器

使用link的场景:在企业开发环境中,我们有一个mysql的服务的容器mysql_1,还有一个web应用程序 web_1,肯定web_1这台容器肯定要连接mysql_1这个数据库。前面网络命名空间的知识告诉我们,两 个容器需要能通信,需要知道对方的具体的IP地址。生产环境还比较好,IP地址很少变化,但是在我们内部测试环境,容器部署的IP地址是可能不断变化的,所以,开发人员不能在代码中写死数据库的IP地 址。这个时候,我们就可以利用容器之间link来解决这个问题。下面,我们来介绍如何通过容器名称来 进行ping,而不是通过IP地址。

docker run -itd --name nginx2 --link nginx1 nginx:1.19.3-alpine
docker exec -it nginx2 sh
ping 172.17.0.2
ping www.baidu.com
ping nginx1

link的作用相当于添加了DNS解析。在nginx1容器里去ping nginx2 容器是不通的,因为link关系是单向的,不可逆。 实际工作中,docker官网已经不推荐我们使用link参数。 docker用其他方式替换掉link参数

新建bridge网络

docker network create -d bridge l-bridge
参数-d 是指DRIVER的类型,后面的l-bridge是network的自定义名称,这个和docker0是类似的。

启动一个nginx的容器nginx3,并通过参数network connect来连接l-bridge网络。在启动容器 nginx3之前,查看目前还没有容器连接到了l-bridge这个网络上。

brctl show
docker network ls
docker network inspect l-bridge
docker run -itd --name nginx3 --network l-bridge nginx:1.19.3-alpine
brctl show
docker network inspect l-bridge

把一个运行中容器连接到 l-bridge网络

docker network connect l-bridge nginx2
docker network inspect l-bridge
docker exec -it nginx2 sh
ping nginx3
docker exec -it nginx3 sh
ping nginx2

none网络

docker run -itd --name nginx1 --network none nginx:1.19.3-alpine
docker network inspect none

注意,容器使用none模式,是没有物理地址和IP地址。我们可以进入到nginx1容器里,执行ip a命令看 看。只有一个lo接口,没有其他网络接口,没有IP。也就是说,使用none模式,这个容器是不能被其他 容器访问。这种使用场景很少,只有项目安全性很高的功能才能使用到。例如:密码加密算法容器。

host网络

docker run -itd --name nginx2 --network host nginx:1.19.3-alpine
docker network inspect host
这里来看,也不显示IP地址。下面我们进入nginx2容器,执行ip a看看效果。我们在容器里执行ip a,发现打印内容和在linux本机外执行ip a是一样的。
docker exec -it nginx2 sh
ip a

容器使用了host模式,说明容器和外层linux主机共享一套网络接口。VMware公司的虚 拟机管理软件,其中网络设置,也有host这个模式,作用也是一样,虚拟机里面使用网络和你自己外层 机器是一模一样的。这种容器和本机使用共享一套网络接口,缺点还是很明显的,例如我们知道web服 务器一般端口是80,共享了一套网络接口,那么你这台机器上只能启动一个nginx端口为80的服务器 了。否则,出现端口被占用的情况。

网络命令汇总

docker network --help
查看网络
docker network ls
作用:查看已经建立的网络对象
命令格式:docker network ls [OPTIONS]
命令参数(OPTIONS):
-f, --filter filter 过滤条件('driver=bridge’)
--format string 格式化打印结果
--no-trunc 不缩略显示
-q, --quiet 只显示网络对象的ID
# 注意:默认情况下,docker安装完成后,会自动创建bridge、host、none三种网络驱动
# 命令演示
docker network ls
docker network ls --no-trunc
docker network ls -f 'driver=host'
创建网络
docker network create
作用:创建新的网络对象
命令格式:docker network create [OPTIONS] NETWORK
命令参数(OPTIONS):
-d, --driver string 指定网络的驱动(默认 "bridge")
--subnet strings 指定子网网段(如192.168.0.0/16、172.88.0.0/24)
--ip-range strings 执行容器的IP范围,格式同subnet参数
--gateway strings 子网的IPv4 or IPv6网关,如(192.168.0.1)
注意:host和none模式网络只能存在一个,docker自带的overlay 网络创建依赖于docker swarm(集群负载均衡)服务
192.168.0.0/16 等于 192.168.0.0~192.168.255.255192.168.8.0/24
172.88.0.0/24 等于 172.88.0.0~172.88.0.255
命令演示
docker network ls
docker network create -d bridge my-bridge
docker network ls
网络删除
docker network rm
 作用:删除一个或多个网络
 命令格式:
docker network rm NETWORK [NETWORK...]
查看网络详细信息
docker network inspect
作用:查看一个或多个网络的详细信息
 命令格式:
docker network inspect [OPTIONS] NETWORK [NETWORK...]
或者 docker inspect [OPTIONS] NETWORK [NETWORK...]
 命令参数(OPTIONS):
-f, --format string 根据format输出结果
使用网络
docker run –-network
作用:为启动的容器指定网络模式
命令格式:
docker run/create --network NETWORK
注意:默认情况下,docker创建或启动容器时,会默认使用名为bridge的网络
网络连接与断开
docker network connect/disconnect
作用:将指定容器与指定网络进行连接或者断开连接
命令格式:
docker network connect [OPTIONS] NETWORK CONTAINER
docker network disconnect [OPTIONS] NETWORK CONTAINER
命令参数(OPTIONS):
-f, --force 强制断开连接(用于disconnect)

练习

docker network create -d bridge --subnet=172.172.0.0/24 --gateway 172.172.0.1
l-network
172.172.0.0/24: 24代表子码掩码是255.255.255.0
172.172.0.0/16: 16 代表子码掩码

docker network ls

docker run -itd --name nginx3 -p 80:80 --net l-network --ip 172.172.0.10
nginx:1.19.3-alpine
--net mynetwork:选择存在的网络
--ip 172.172.0.10:给nginx分配固定的IP地址

docker network inspect l-network
docker stop nginx3
docker start nginx3
docker network inspect l-network

docker数据卷

在使用docker容器的时候,会产生一系列的数据文件,这些数据文件在我们删除docker容器时是 会消失的,但是其中产生的部分内容我们是希望能够把它给保存起来另作用途的,Docker将应用与运行 环境打包成容器发布,我们希望在运行过程钟产生的部分数据是可以持久化的的,而且容器之间我们希 望能够实现数据共享。

通俗地来说,docker容器数据卷可以看成使我们生活中常用的u盘,它存在于一个或多个的容器中,由 docker挂载到容器,但不属于联合文件系统,Docker不会在容器删除时删除其挂载的数据卷。

特点:

  1. 数据卷可以在容器之间共享或重用数据
  2. 数据卷中的更改可以立即生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷默认会一直存在,即使容器被删除
  5. 数据卷的生命周期一直持续到没有容器使用它为止

容器中的管理数据主要有两种方式:

  • 数据卷:Data Volumes 容器内数据直接映射到本地主机环境
  • 数据卷容器:Data Volume Containers 使用特定容器维护数据卷

数据卷类型

有三种数据卷类型:

  1. 宿主机数据卷:直接在宿主机的文件系统中但是容器可以访问(bind mount)
  2. 命名的数据卷:磁盘上Docker管理的数据卷,但是这个卷有个名字。
  3. 匿名数据卷:磁盘上Docker管理的数据卷,因为没有名字想要找到不容易,Docker来管理这些文 件。

数据卷其实都在(如果没有网络文件系统等情况下)宿主机文件系统里面的,只是第一种是在宿主机内 的特定目录下,而后两种则在docker管理的目录下,这个目录一般是 /var/lib/docker/volumes/

宿主机数据卷

bind mounts:容器内的数据被存放到宿主机文件系统的任意位置,甚至存放到一些重要的系统目录或 文件中。除了docker之外的进程也可以任意对他们进行修改。

当使用bind mounts时,宿主机的目录或文件被挂载到容器中。容器将按照挂载目录或文件的绝对路径 来使用或修改宿主机的数据。宿主机中的目录或文件不需要预先存在,在需要的使用会自动创建。

使用bind mounts在性能上是非常好的,但这依赖于宿主机有一个目录妥善结构化的文件系统。

使用bind mounts的容器可以在通过容器内部的进程对主机文件系统进行修改,包括创建,修改和删除 重要的系统文件和目录,这个功能虽然很强大,但显然也会造成安全方面的影响,包括影响到宿主机上 Docker以外的进程

数据覆盖问题:

  • 如果挂载一个空的数据卷到容器中的一个非空目录中,那么这个目录下的文件会被复制到数据卷中
  • 如果挂载一个非空的数据卷到容器中的一个目录中,那么容器中的目录会显示数据卷中的数据。如 果原来容器中的目录有数据,那么原始数据会被隐藏掉
docker run -v /宿主机绝对路径目录:/容器内目录 镜像名

docker run -itd --name mysql --restart always --privileged=true -p 3306:3306 -e MYSQL_ROOT_PASSWORD=admin -v /data/mysql:/var/lib/mysql mysql:5.7.31 --character-set-server=utf8 --collation-server=utf8_general_ci

容器目录权限

通过 -v 容器内路径: ro rw 改变读写权限
ro:readonly 只读
rw:readwrite 可读可写
docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
docker run -it -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
例如:
docker run -d -P --name nginx05 -v ledu1:/etc/nginx:ro nginx
docker run -d -P --name nginx05 -v ledu2:/etc/nginx:rw nginx
ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!

挂载目录权限问题

docker run -d -p 8081:8081 --name nexus3 -v /data/nexus3/:/nexus-data/
sonatype/nexus3:3.28.1
查看容器启动日志
docker logs -f nexus3
报错信息如下:
mkdir: cannot create directory '../sonatype-work/nexus3/log': Permission denied
mkdir: cannot create directory '../sonatype-work/nexus3/tmp': Permission denied
OpenJDK 64-Bit Server VM warning: Cannot open file ../sonatype-work/nexus3/log/jvm.log due to No such file or directory
Warning: Cannot open log file: ../sonatype-work/nexus3/log/jvm.log
Warning: Forcing option -XX:LogFile=/tmp/jvm.log
java.io.FileNotFoundException: ../sonatypework/nexus3/tmp/i4j_ZTDnGON8hezynsMX2ZCYAVDtQog=.lock (No such file or
directory)
....

查看官网说明文档,需要为挂载目录授权
chown -R 200 nexus3/
命名的数据卷
docker run -itd --name nginx -p 80:80 -v l-nginx:/etc/nginx nginx:1.19.3-alpine
查看docker数据卷
docker volume ls
查看ledu-nginx宿主机目录
docker volume inspect ledu-nginx
进入docker数据卷默认目录
cd /var/lib/docker/volumes/ledu-nginx
查看文件
ls
所有的文件docker默认保存在_data目录中
cd _data
删除容器
docker rm $(docker stop $(docker ps -aq))
查看挂载数据是否还存在,通过查看数据,发现删除容器后,宿主机中的数据还存在
ls

数据卷容器

如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷供其他容器挂载。

创建好的数据卷容器是处于停止运行的状态,因为使用 --volumes-from 参数所挂载数据卷的容器 自己并不需要保持在运行状态。

Docker_第4张图片

docker run -d --name data-volume -v /data/nginx:/usr/share/nginx/html -v /data/mysql:/var/lib/mysql centos:7.8.2003
docker run -itd --name nginx01 -p 80:80 --volumes-from data-volume nginx:1.19.3-alpine

echo "ledu nginx" > /data/nginx/index.html

docker run -itd --name nginx02 -p 81:80 --volumes-from data-volume nginx:1.19.3-alpine

docker run -itd --name mysql01 --restart always --privileged=true -p 3306:3306 -e MYSQL_ROOT_PASSWORD=admin --volumes-from data-volume mysql:5.7.31 --character-set-server=utf8 --collation-server=utf8_general_ci

docker run -itd --name mysql02 --restart always --privileged=true -p 3307:3306-e MYSQL_ROOT_PASSWORD=admin --volumes-from data-volume mysql:5.7.31 --character-set-server=utf8 --collation-server=utf8_general_ci

docker-compose

官网地址

compose 是用来定义和运行一个或多个容器(通常都是多个)运行和应用的工具。使用 compose 可以简 化容器镜像的构建以及容器的运行。

compose 使用 YAML 文件来定义多容器之间的关系。一个 docker-compose up 就可以把完整的应用跑 起来。 本质上, compose 把 YAML 文件解析成 docker 命令的参数,然后调用相应的 docker 命令行 接口,从而将应用以容器化的方式管理起来。它通过解析容器间的依赖关系顺序地启动容器。而容器间 的依赖关系由 YAML 文件中的 links 标记指定。

Docker Compose能够在 Docker 节点上,以单引擎模式(Single-Engine Mode)进行多容器应用的部 署和管理。多数的现代应用通过多个更小的微服务互相协同来组成一个完整可用的应用。

微服务部署和管理繁多的服务是困难的。而这正是 Docker Compose 要解决的问题。Docker Compose 并不 是通过脚本和各种冗长的 docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整 个应用,从而使用一条命令完成部署。应用部署成功后,还可以通过一系列简单的命令实现对其完整声 明周期的管理。甚至,配置文件还可以置于版本控制系统中进行存储和管理。

docker compose安装

下载:https://github.com/docker/compose

授权:chmod 777 /usr/local/bin/docker-compose

检查安装情况以及版本

docker-compose -v
docker-compose --version
docker-compose version

卸载docker-compose

rm -rf /usr/local/bin/docker-compose
docker-compose卸载只需要删除二进制文件就可以了。

docker compose 默认使用文件名 docker-compose.yml,也可以使用 -f 参数指定具体文件。

Docker Compose 的 YAML 文件包含 4 个一级 key:version、services、networks、volumes

  • version 是必须指定的,而且总是位于文件的第一行。它定义了 Compose 文件格式(主要是 API)的版本。注意,version 并非定义 Docker Compose 或 Docker 引擎的版本号。
  • services 用于定义不同的应用服务。上边的例子定义了两个服务:一个名为 l-mysql数据库服 务以及一个名为l-eureka的微服。Docker Compose 会将每个服务部署在各自的容器中。
  • networks 用于指引 Docker 创建新的网络。默认情况下,Docker Compose 会创建 bridge 网络。 这是一种单主机网络,只能够实现同一主机上容器的连接。当然,也可以使用 driver 属性来指定不 同的网络类型。
  • volumes 用于指引 Docker 来创建新的卷。

docker-compose.yml

version: '3'
services:
  l-nginx:
    restart: always
    container_name: l-nginx
    volumes:
    - /data/nginx:/etc/nginx
    image: nginx:1.19.3-alpine
    ports:
    - 80:80
  l-tomcat1:
    restart: always
    container_name: l-tomcat1
    volumes:
    - /data/tomcat1/webapps:/usr/local/tomcat/webapps
    image: tomcat:9.0.20-jre8-alpine
    ports:
    - 8081:8080
    depends_on:
    - l-nginx
  l-tomcat2:
    restart: always
    container_name: l-tomcat2
    volumes:
    - /data/tomcat2/webapps:/usr/local/tomcat/webapps
    image: tomcat:9.0.20-jre8-alpine
    ports:
    - 8082:8080
    depends_on:
    - l-nginx

docker compose常用命令

启动服务
docker-compose up -d

停止服务
docker-compose down

列出所有运行容器
docker-compose ps

查看服务日志
docker-compose logs

构建或者重新构建服务
docker-compose build

启动服务
docker-compose start

停止已运行的服务
docker-compose stop

重启服务
docker-compose restart

官网地址
https://docs.docker.com/compose/reference/build

Dockerfile

官网地址

Dockerfile其实就是我们用来构建Docker镜像的源码,是一些命令的集合,只要理解它的逻辑和语法格式,就可以很容易的编写Dockerfile。简单点说,Dockerfile可以让用户个性化定制Docker镜像。因为工作环境中的需求各式各样,网络上的镜像很难满足实际的需求。

Dockerfile的基本结构

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

docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用 -f 标志指向文件系统中任 何位置的Dockerfile。

Dockerfile由一行行命令语句组成,并且支持以#开头的注释行

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

Dockerfile文件说明

Docker以从上到下的顺序运行Dockerfile的指令。为了指定基本映像,第一条指令必须是FROM。一个声 明以 # 字符开头则被视为注释。可以在Docker文件中使用 RUN , CMD , FROM , EXPOSE , ENV 等指令。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GoJ0xFL0-1676086417326)(C:\Users\0\AppData\Roaming\Typora\typora-user-images\image-20230210214655642.png)]

build命令

docker build 命令用于使用 Dockerfile 创建镜像。

docker build [OPTIONS] PATH | URL | -
常用参数
--build-arg=[] :设置镜像创建时的变量;
-f :指定要使用的Dockerfile路径;
--rm :设置镜像成功后删除中间容器;
--tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置
多个标签。

Dockerfile部署项目

优化mysql镜像

Dockerfile文件:

FROM mysql:5.7.31
# 作者信息
MAINTAINER mysql from date UTC by Asia/Shanghai "l"
ENV TZ Asia/Shanghai
# 初始化数据库
COPY l.sql /docker-entrypoint-initdb.d
创建镜像mysql镜像
docker build --rm -t mymysql:v1 .
制作项目镜像
FROM openjdk:8-alpine3.9
# 作者信息
MAINTAINER l Docker springboot "l"
# 修改源
RUN echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" >
/etc/apk/repositories && \
echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >>
/etc/apk/repositories
# 安装需要的软件,解决时区问题
RUN apk --update add curl bash tzdata && \
rm -rf /var/cache/apk/*
#修改镜像为东八区时间
ENV TZ Asia/Shanghai
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
EXPOSE 8082
ENTRYPOINT ["java","-jar","/app.jar"]

生成测试镜像

docker build --rm -t l/dockerdemo:v1 --build-arg JAR_FILE=dockerdemo.jar .

idea集成docker

修改服务器docker.service服务信息,允许其他主机远程访问服务器的docker。

vi /usr/lib/systemd/system/docker.service
在ExecStart行最后增加,开放远程主机访问权限。
-H tcp://0.0.0.0:2375

最后增加修改内容如下:
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375

重启docker
systemctl daemon-reload
systemctl restart docker

查看docker进程,发现docker守护进程在已经监听2375的tcp端口
ps -ef|grep docker

查看系统的网络端口,检查tcp的2375端口,docker的守护进程是否监听
netstat -tulp

配置idea

settings->build execution…->docker->点击"+"按钮,新增服务器docker配置信息

配置内容如下:
name:docker
TCP Socket:
	Engine API URL:tcp://192.168.1.100:2375
配置成功后,会在下方显示connection successful

第三部分 Docker运维管理

Swarm集群管理

节点信息
Docker_第5张图片
安装docker-swarm

Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排项目,但不同的是,Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,可以将组成某个应该的多个docker容器 编排在一起,同时管理。而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,其主要作 用是把若干台Docker主机抽象为一个整体,并且通过一个入口(docker stack)统一管理这些Docker主 机上的各种Docker资源。

stack 是构成特定环境中的 service 集合, 它是自动部署多个相互关联的服务的简便方法,而无需单独定 义每个服务。

stack file 是一种 yaml 格式的文件,类似于 docker-compose.yml 文件,它定义了一个或多个服务,并 定义了服务的环境变量、部署标签、容器数量以及相关的环境特定配置等。

Docker Swarm由两部分组成:

  • Docker集群:将一个或多个Docker节点组织起来,用户就能以集群的方式进行管理;
  • 应用编排:有一套API用来部署和管理容器

Docker_第6张图片

初始化第一个管理节点

docker swarm init --advertise-addr 192.168.198.105:2377 --listen-addr
192.168.198.105:2377
关于advertise-addr和listen-addr这两个参数:
前者用来指定其他节点连接m0时的地址,后者指定承载swarm流量的IP和端口,会在本地新建docker网络

加入新的节点

Docker Swarm的新节点加入策略是从管理节点获取一长串命令,被称为join token,任何想加入集群的 机器只要自己执行这个join token即可加入Swarm集群;

新的管理节点需要加入,在m0执行命令docker swarm join-token manager即可得到管理 manager节点的join token

新的work节点需要加入,在m0执行命令docker swarm join-token worker即可得到管理work节 点的join token

docker node ls

manager节点说明

MANAGER STATUS列说明:

  • Leader 意味着该节点是使得群的所有群管理和编排决策的主要管理器节点。
  • Reachable 意味着节点是管理者节点正在参与Raft共识。如果领导节点不可用,则该节点有资格被选为新领导者。
  • Unavailable 意味着节点是不能与其他管理器通信的管理器。如果管理器节点不可用,您应该将新的管理器节点加入群集,或者将工作器节点升级为管理器。

AVAILABILITY列说明:

  • Active 意味着调度程序可以将任务分配给节点。
  • Pause 意味着调度程序不会将新任务分配给节点,但现有任务仍在运行。
  • Drain 意味着调度程序不会向节点分配新任务。调度程序关闭所有现有任务并在可用节点上调度它们。

验证节点:docker info

节点权限提升/降低

将worker节点提升为manager节点,在manager节点执行如下命令:

docker node promote work-01
docker node ls

将manager节点降低为worker节点,在manager节点执行如下命令:

docker node demote work-02
docker node ls

脱离集群

在work-02节点使用命令:docker swarm leave 稍微等待几分钟,在manager节点使用命令:docker node ls,发现work-02节点已经脱离集群管理。

删除脱离集群的节点

先使用命令:docker node demote 节点名称。将某一个节点降为worker节点后,再删除。
使用命令:docker node rm 节点名称|节点ID
例如:docker node rm work-02
manager节点只能强制退出。命令:docker swarm leave --force。manager退出后意味着整个swarm不复存在。

图形界面

https://hub.docker.com/r/dockersamples/visualizer

拉取镜像

docker pull dockersamples/visualizer:latest

运行镜像

docker run -itd --name visualizer -p 8099:8080 -e HOST=192.168.198.105 -e PORT=8080 -v /var/run/docker.sock:/var/run/docker.sock dockersamples/visualizer:latest

docker service create \
--name=viz \
--publish=8080:8080/tcp \
--constraint=node.role==manager \
--mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer

swarm命令

Docker_第7张图片

node命令

Docker_第8张图片

service命令

Docker_第9张图片

Service和Reolicas

Docker_第10张图片

部署nginx
在manager节点中创建overlay网络:
docker network create -d overlay nginx-net

创建5个nginx:alpines容器的集群:
docker service create --name nginx --network nginx-net -p 80:80 --replicas 5
nginx:1.18.0-alpine

在manager节点使用docker service ls 命令查看服务情况,worker节点无法查看:
docker service ls

在manager或者worker节点都可以执行docker ps命令查看本虚拟机容器情况:
docker ps

manager节点只用于管理集群,不希望部署服务。
docker node update --availability drain master-01

使用docker service scale nginx=2命令将服务缩减为2个容器:
docker service scale nginx=2
升级nginx版本
进入其中一个容器查看nginx的版本信息:
注意事项:因nginx是alpine的linux版本。不能使用/bin/bash指令。
docker exec -it 503fe639bb89 sh
nginx -v

1.更新镜像:
docker service update --image nginx:1.19.3-alpine nginx

2.添加或者更新一个对外端口:
docker service update --publish-add 8090:80 nginx
删除服务
docker service rm nginx
docker network rm nginx-net

stack命令

Docker_第11张图片

部署nginx

docker-compose.yml

version: "3"
services:
	nginx-web:
		image: nginx:1.19.3-alpine
		container_name: nginx
		networks:
			- nginx-net
		restart: always
		ports:
			- 80:80
		deploy:
			replicas: 5
networks:
	nginx-net:
		driver: overlay
运行nginx
在manager节点中创建docker-compose.yml文件。执行如下命令:
docker stack deploy nginx-stack --compose-file=docker-compose.yml 或者是
docker stack deploy nginx-stack -c docker-compose.yml

查看stack服务运行情况。执行如下命令:
docker stack services nginx-stack

查看5个容器运行在哪个节点中。执行如下命令:
docker service ls 查看到NAME中的服务名为:nginx-stack_nginx-web

docker service ps nginx-stack_nginx-web

进行测试:
curl 192.168.0.105
curl 192.168.0.106
curl 192.168.0.107

删除stack服务。执行如下命令:
docker stack rm nginx-stack

总结:

  • networks中也可以不指定driver:overlay,因为docker swarm默认网络类型是overlay。
  • 整个networks都可以不用配置。stack部署时会默认创建网络。如果我们定义网络。在docker stack deploy时会先默认创建一个网络,在创建一个我们定义的网络。
  • 一定要把镜像先拉取到本地再执行

Docker Stack和Docker Compose区别

Docker stack会忽略了“构建”指令,无法使用stack命令构建新镜像,它是需要镜像是预先已经构建 好的。 所以docker-compose更适合于开发场景;

Docker Compose是一个Python项目,在内部,它使用Docker API规范来操作容器。所以需要安 装Docker -compose,以便与Docker一起在您的计算机上使用;

Docker Stack功能包含在Docker引擎中。不需要安装额外的包来使用它,docker stacks 只是 swarm mode的一部分。

Docker stack不支持基于第2版写的docker-compose.yml ,也就是version版本至少为3。然而 Docker Compose对版本为2和3的 文件仍然可以处理;

docker stack把docker compose的所有工作都做完了,因此docker stack将占主导地位。同时, 对于大多数用户来说,切换到使用docker stack既不困难,也不需要太多的开销。如果您是Docker新手,或正在选择用于新项目的技术,请使用docker stack。

你可能感兴趣的:(简单就完事了,docker,linux,运维)