Docker笔记与使用_网用里bb4bf4-程序员宅基地

技术标签: 笔记  docker  

Docker学习

  • Docker概述
  • Docker安装
  • Docker命令
    • 镜像命令
    • 容器命令
    • 操作命令
  • Docker镜像
  • 容器数据卷
  • DockerFile
  • Docker网络原理
  • IDEA整合Docker
  • Docker Compose
  • Docker Swarm
  • CI\CD jenkins

Docker概述

Docker为什么出现?

一款产品:开发-上线 两套环境!应用环境,应用配置!

传统的开发模式是:开发人员开发应用程序,运维来部署环境。而此种模式会带来一种问题,就是在开发人员的电脑中程序可以运行起来,而在其它地方程序无法运行。环境冲突的问题导致程序无法正常执行

而Docker的解决方法是:

  • Docker的思想模式是来自于集装箱
  • 在多个应用(端口冲突)–原来都是交叉的
  • 隔离:Docker核心思想!打包装箱!每个箱子都是互相隔离的
  • Docker通过隔离机制,可以将服务器利用到机制

本质:所有的技术都是因为出现了一些问题,我们需要去解决,才去学习

Docker历史

2010年,几个搞IT的年轻人,就在美国成立了一家公司dotcloud

做一些pass的云计算服务!LXC有关的容器技术!

他们将自己的技术(容器化技术)命名及时Docker!

Docker在给刚刚诞生的时候,没有引起行业的注意!dotCloud,就无法活不下去!

2013年,将Docker开源!

Docker越来越多的人发现了Docker的优点,Docker每个月都会更新一个版本

2014年4月9日,Docker1.0发布

Docker为什么这么火?十分的轻巧!

在容器技术出来之前,我们都是使用的虚拟机技术!

虚拟机:在window中装一个Vmware,通过这个软件我们可以虚拟出来一个或者多台电脑!但是比较笨重!

虚拟机也是属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!

vm, Linux centos原生镜像(一个电脑) 隔离,需要开启多个虚拟机! 几个G 几分钟
docker,隔离, 镜像(最核心的环境 4m + jdk + mysql)十分的轻巧, 运行镜像就可以了!小巧!几个M KB 秒级启动!

到现在,所有的开发人员都必须要回Docker

聊聊Docker

Docker是基于GO语言开发的!开源项目!

官网:https://www.docker.com/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yu7Kymwd-1623469059437)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/image-20210514095514860.png)]

仓库地址:https://hub.docker.com/

Docker能做什么

虚拟机技术

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6bcuOFtX-1623469059440)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210514114532.png)]

虚拟机技术缺点:

  1. 资源占用十分多
  2. 冗余步骤多
  3. 启动很慢

容器化技术

容器化技术不是模拟的一个玩这个的操作系统

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LGbZz7ZL-1623469059443)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210514115007.png)]

比较Docker和虚拟机技术的不同

  1. 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
  2. 容器内的应用直接运行在宿主机的内部,容器时没有自己的内核的,也没有虚拟我们的硬件,所有就轻便了许多
  3. 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互补影响

DevOps(开发、运维)

应用更快捷的交付和部署

传统:一堆的帮助文档, 安装程序

Docker:打包镜像发布测试,一键运行

更便捷的升级和扩缩容

使用了Docker之后,我们部署应用就和搭积木一样!

项目打包为一个镜像,扩展服务器A!服务器B!

更简单的系统运维

在容器化之后,我们的开发和测试的环境都是高度一致

更高效的计算资源利用

Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多的容器实例!服务器的性能可以被压缩到极致。

Docker安装

Docker的名词

Docker架构图

镜像(image)

docker净吸纳过就好比是一个模板,可以通过这个模板来创建容器服务,Tomcat镜像===> run ===> Tomcat01容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)

容器(container)

Docker利用容器技术,独立运行一个或者一个组应用,通过镜像来创建的。

启动,停止,删除,基本命令!

目前就可以把这个容器理解为就是一个简易的Linux系统

仓库(repository)

仓库就是存放镜像的地方!

仓库分为公有仓库和私有仓库

Docker Hub(默认都是国外的)

阿里云、华为云都有容器服务器(配置镜像加速)

安装Docker

环境准备

  1. 需要会一点点的Linux基础
  2. centos7
  3. 使用Xshell来连接服务器
# 系统内核是3.10以上的
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# uname -r
3.10.0-1160.24.1.el7.x86_64

# 
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装

帮助文档

  1. 安装gcc相关环境
yum -y install gcc
yum -y install gcc-c++
  1. 卸载旧的docker安装包
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  1. 需要的安装包
yum install -y yum-utils
  1. 设置镜像的仓库
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo  # 默认是国外的

yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 阿里云地址
  1. 更新yum软件包索引
yum makecache fast
  1. 安装Docker相关的内容docker-ce 社区版docker-ee企业版
yum install -y docker-ce docker-ce-cli containerd.io
  1. 启动Docker
systemctl start docker
  1. 使用Docker version来查看是否安装成功
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker version
Client: Docker Engine - Community
 Version:           20.10.6
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        370c289
 Built:             Fri Apr  9 22:45:33 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.6
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       8728dd2
  Built:            Fri Apr  9 22:43:57 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.4
  GitCommit:        05f951a3781f4f2c1911b05e61c160e9c30eaa8e
 runc:
  Version:          1.0.0-rc93
  GitCommit:        12644e614e25b05da6fd08a38ffa0cfe1903fdec
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
  1. 测试hello-world程序
docker run hello-world
  1. 查看一下下载的这个hello-world镜像是否存在
docker images
  1. 卸载Docker
 # 1. 卸载依赖
 yum remove docker-ce docker-ce-cli containerd.io
 
 # 2. 删除资源
 rm -rf /var/lib/docker
 rm -rf /var/lib/containerd

阿里云镜像加速

  1. 登录阿里云官网
  2. 从产品里面的弹性计算里面的容器镜像服务(阿里云的内网使用)

run执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OUdGWvPM-1623469059448)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/未命名文件.jpg)]

底层原理

Docker是怎么工作的?

Docker是一个Client - Server 结构的系统, Docker的守护进程运行在主机上。通过Socket从客户端访问!

DockerServer接收到Docker-Client 的指令,就会执行这个命令!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7prKYQUK-1623469059450)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/未命名文件 (1)].jpg)

Docker为什么要比VM快

  1. Docker有着比虚拟机更少的抽象层
  2. Docker利用的是宿主机的内核,VM需要的是Guest OS

所以说,新建一个容器的时候,Docker不需要像虚拟机重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,分钟级别启动的,而Docker是利用宿主机的操作系统的,省略了这个复杂的过程,是秒级启动的。

Docker的常用命令

帮助命令

docker version		 # 显示docker的版本信息
docker info			 # 显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help	#万能命令

帮助文档的地址:https://docs.docker.com/reference/

镜像命令

docker images 查看所有本地的主机上的镜像

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   2 months ago   13.3kB

REPOSITORY  镜像的仓库源
TAG         镜像的标签
IMAGE ID    镜像的ID
CREATED     镜像的创建时间
SIZE        镜像的大小

-a, --all             列出所有镜像
-q, --quiet           只显示镜像的ID

docker search 搜索命令

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker search mysql
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   10873     [OK]       
mariadb                           MariaDB Server is a high performing open sou…   4099      [OK]       
mysql/mysql-server                Optimized MySQL Server Docker images. Create…   806                  [OK]
percona                           Percona Server is a fork of the MySQL relati…   536       [OK]       

docker pull 下载镜像

# 下载镜像 dockerpull 镜像名[:tag]
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker pull mysql
Using default tag: latest  # 如果不写 tag , 默认就是latest
latest: Pulling from library/mysql
69692152171a: Pull complete  # 分层下载,docker image的核心 联合文件系统
1651b0be3df3: Pull complete 
951da7386bc8: Pull complete 
0f86c95aa242: Pull complete 
37ba2d8bd4fe: Pull complete 
6d278bb05e94: Pull complete 
497efbd93a3e: Pull complete 
f7fddf10c2c2: Pull complete 
16415d159dfb: Pull complete 
0e530ffc6b73: Pull complete 
b0a4a1a77178: Pull complete 
cd90f92aa9ef: Pull complete 
Digest: sha256:d50098d7fcb25b1fcb24e2d3247cae3fc55815d64fec640dc395840f8fa80969
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest # 真是地址

docker pull mysql
docker pull docker.io/library/mysql:latest
# 以上的两条命令是一样的

# 指定版本的镜像
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
69692152171a: Already exists 
1651b0be3df3: Already exists 
951da7386bc8: Already exists 
0f86c95aa242: Already exists 
37ba2d8bd4fe: Already exists 
6d278bb05e94: Already exists 
497efbd93a3e: Already exists 
a023ae82eef5: Pull complete 
e76c35f20ee7: Pull complete 
e887524d2ef9: Pull complete 
ccb65627e1c3: Pull complete 
Digest: sha256:a682e3c78fc5bd941e9db080b4796c75f69a28a8cad65677c23f7a9f18ba21fa
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7


docker rmi 删除镜像

# 删除指定的镜像
docker rmi -f 镜像ID

# 删除多个的镜像
docker rmi -f 镜像ID 镜像ID 镜像ID

# 删除全部的镜像
docker rmi -f $(docker images -aq)

容器命令

说明:我们欧了镜像才可以创建容器,Linux,下载一个centos镜像来测试

docker pull centos

新建容器并启动

docker run [可选参数] image
# 参数说明
--name="Name" 容器名字 Tomcat01 Tomcat02 用来区分容器
-d 		      后台方式运行
-it           使用交互方式运行,进入容器查看内容
-P            指定容器的端口 -P 8080:8080
	-P ip:主机端口:容器端口
	-P 主机端口:容器端口
	-P 容器端口
	容器端口
-p            随机指定端口


# 启动并进入容器
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -it centos /bin/bash
[root@a05ab38c8636 /]# ls # 查看容器内的centos, 基本版本,有很多的命令并不完善
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 启动NGINX实例
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -d -p 3344:80 --name nginx02 nginx
bc6810eee3480b464733575829a48b4d9a7e573697dc25f74934db0598ed989b


# 从容器中退出
[root@a05ab38c8636 /]# exit
exit


列出所有运行中的容器

# docker ps 命令

-a # 累出当前正在运行的容器+历史运行的容器
-n=? # 最近创建的容器
-q # 只显示容器的编号

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker ps -a
CONTAINER ID   IMAGE         COMMAND       CREATED         STATUS                      PORTS     NAMES
a05ab38c8636   centos        "/bin/bash"   3 minutes ago   Exited (0) 51 seconds ago             hopeful_darwin
3059f7efd070   hello-world   "/hello"      2 hours ago     Exited (0) 2 hours ago                vigilant_rubin
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# 

退出容器

exit # 直接容器停止并退出
Ctrl + p + q # 容器不停止退出

删除容器

docker rm 容器ID   # 删除指定的容器, 不能删除正在运行的容器,如果要强制删除, rm -f 
docker rm -r $(docker ps -aq) # 删除全部的容器
docker ps -a -q|xargs docker rm # 删除所有的容器

启动和停止容器的操作

docker start 容器ID   # 启动容器
docker restart 容器ID # 重启容器
docker stop 容器ID    # 停止当前正在运行容器
docker kill 容器ID    # 轻质停止当前容器

常用的其他命令

后台启动容器

# 命令 docker run -d 精明名
docker run -d centos

常见的坑,docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用,就会自动停止

NGINX,容器启动后,发现自己没有提供服务,就会立刻停止

查看日志

docker logs -f -t --tail 容器

# 显示日志
-tf #显示日志
--tial number # 要显示日志的条数
docker logs -tf --tail 10 300e315adb2f

查看容器中的进程信息 PS

# docker top 容器ID

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker top 3565dac1ec32
UID            PID              PPID             C                STIME               TTY 
root          13848             13828            0                15:59               ?   
root           13921            13848            0                15:59               ?   

查看镜像的元数据

# docker inspect 容器ID

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker inspect 3565dac1ec32
[
    {
    
        "Id": "3565dac1ec32c34dbcdc651c538238e36a52e53fef729da7876aca893c5ae8c7",
        "Created": "2021-05-14T07:59:30.176021788Z",
        "Path": "/bin/sh",
        "Args": [
            "-c",
            "while true;do echo aa; sleep 1; done"
        ],
        "State": {
    
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 13848,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-05-14T07:59:30.553009964Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55",
        "ResolvConfPath": "/var/lib/docker/containers/3565dac1ec32c34dbcdc651c538238e36a52e53fef729da7876aca893c5ae8c7/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/3565dac1ec32c34dbcdc651c538238e36a52e53fef729da7876aca893c5ae8c7/hostname",
        "HostsPath": "/var/lib/docker/containers/3565dac1ec32c34dbcdc651c538238e36a52e53fef729da7876aca893c5ae8c7/hosts",
        "LogPath": "/var/lib/docker/containers/3565dac1ec32c34dbcdc651c538238e36a52e53fef729da7876aca893c5ae8c7/3565dac1ec32c34dbcdc651c538238e36a52e53fef729da7876aca893c5ae8c7-json.log",
        "Name": "/peaceful_einstein",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "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,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "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": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
    
            "Data": {
    
                "LowerDir": "/var/lib/docker/overlay2/da103020cf947821a9b717c70b556c0b2658ddc3e14af9585242965f1038c7b6-init/diff:/var/lib/docker/overlay2/7ae992f7b556a66ecbc14cc40e0df81da30ac28feffa45999a4e389d0e68bfed/diff",
                "MergedDir": "/var/lib/docker/overlay2/da103020cf947821a9b717c70b556c0b2658ddc3e14af9585242965f1038c7b6/merged",
                "UpperDir": "/var/lib/docker/overlay2/da103020cf947821a9b717c70b556c0b2658ddc3e14af9585242965f1038c7b6/diff",
                "WorkDir": "/var/lib/docker/overlay2/da103020cf947821a9b717c70b556c0b2658ddc3e14af9585242965f1038c7b6/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
    
            "Hostname": "3565dac1ec32",
            "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",
                "while true;do echo aa; sleep 1; done"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
    
                "org.label-schema.build-date": "20201204",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
    
            "Bridge": "",
            "SandboxID": "dca9b4cec16049ee9eea3ef3f69832c54a4bbe5e07bc92d1716f07924b748dbd",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
    },
            "SandboxKey": "/var/run/docker/netns/dca9b4cec160",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "9b128f7836259194f4ef26a30d52141755432956388c6b8f69916a593f6bc808",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
    
                "bridge": {
    
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "83e597ad26efff30e939cf0d4300ea418aae59880a638c6153cec986c5d663dc",
                    "EndpointID": "9b128f7836259194f4ef26a30d52141755432956388c6b8f69916a593f6bc808",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

进入当前正在运行的容器

# 我们通常容器都是使用的后台方式运行的,需要进入容器,修改一些配置

docker exec -it 容器ID /bin/bash

docker attach 容器ID

# docker exec    # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach  # 进入容器正在执行的终端,不会启动新的进程

从容器内拷贝文件到主机上

# docker cp 容器ID:容器文件的地址 宿主机的地址

docker cp 4d9d244f926f:/home/aa.java /home

可视化

  • portainer(先用这个)
docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
  • Rancher(CI\CD)

什么portainer

Docker图形化界面管理工具!提供一个后台面板供我们操作

docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer

访问测试:外网:8088

Docker镜像讲解

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件

所有的应用,直接打包Docker镜像,就可以直接跑起来

如何得到镜像

  • 从远程仓库下载
  • 配有拷贝给你
  • 自己制作一个镜像DockerFile

Docker镜像加载原理

UnionFS(联合文件系统)

我们下载的时候看到的一层层的就是这个

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

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

Docker镜像加载原理

Docker的镜像实际上是由一层一层的文件系统组成,这种层级的文件系统UnionFS

bootfs(boot file system)主要包括bootloader和kernel,bootloader主要就是引导加载kernel,Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs,这一层与我们典型的Linux/Unix系统是一样的,包括boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs

rootfs(root file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件,rootfs就是各种不同的操作系统的发行版,比如Ubuntu,centos等等

平时我们安装进虚拟机的centos系统都有几个GB,为什么docker才200MB

对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用host和kernel,自己值需要童工rootfs就可以了,由此可见对于不同Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs

虚拟机是分钟级别,容器时秒级

分层理解

分层的镜像

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
69692152171a: Already exists 
a4a46f2fd7e0: Pull complete 
bcdf6fddc3bd: Pull complete 
b7e9b50900cc: Pull complete 
5f3030c50d85: Pull complete 
63dae8e0776c: Pull complete 
Digest: sha256:365eddf64356169aa0cbfbeaf928eb80762de3cc364402e7653532bcec912973
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest

为什么Docker要采用这种分层的结构

最大的好处,莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以别共享

查看镜像分层的方式可以通过 docker image inspect 命令

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker image inspect redis
[
    {
    
        "Id": "sha256:bc8d70f9ef6cae366eb6423fcb4699597c5a6b99126f3ced35b6b9d6d134375b",
        "RepoTags": [
            "redis:latest"
        ],
        "RepoDigests": [
            "redis@sha256:365eddf64356169aa0cbfbeaf928eb80762de3cc364402e7653532bcec912973"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-05-12T19:07:40.989268815Z",
        "Container": "7f80d5e2c33e07cfd43daf9e5b15825833a69ff09cf999c562b325c5f2b1a177",
        "ContainerConfig": {
    
            "Hostname": "7f80d5e2c33e",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
    
                "6379/tcp": {
    }
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.2.3",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.3.tar.gz",
                "REDIS_DOWNLOAD_SHA=98ed7d532b5e9671f5df0825bb71f0f37483a16546364049384c63db8764512b"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"redis-server\"]"
            ],
            "Image": "sha256:c55155952d103fdae7acc2a5d613050c83fed8710409072bf456ed45ac1f9ee5",
            "Volumes": {
    
                "/data": {
    }
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {
    }
        },
        "DockerVersion": "19.03.12",
        "Author": "",
        "Config": {
    
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
    
                "6379/tcp": {
    }
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.12",
                "REDIS_VERSION=6.2.3",
                "REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-6.2.3.tar.gz",
                "REDIS_DOWNLOAD_SHA=98ed7d532b5e9671f5df0825bb71f0f37483a16546364049384c63db8764512b"
            ],
            "Cmd": [
                "redis-server"
            ],
            "Image": "sha256:c55155952d103fdae7acc2a5d613050c83fed8710409072bf456ed45ac1f9ee5",
            "Volumes": {
    
                "/data": {
    }
            },
            "WorkingDir": "/data",
            "Entrypoint": [
                "docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 105384748,
        "VirtualSize": 105384748,
        "GraphDriver": {
    
            "Data": {
    
                "LowerDir": "/var/lib/docker/overlay2/a3d262fe90e54560c0b13f2cb515d554c056dcf660af5ffa87802e91b9a73eb8/diff:/var/lib/docker/overlay2/ac6227ff51b65b18a0cac529ad1318d43d01fc39d14f5b45b34f4326e961cc87/diff:/var/lib/docker/overlay2/fae797250cd99c97520e32ffd7e8c08c9092a60f1b3a5c5dd308b64b4aa33c4f/diff:/var/lib/docker/overlay2/987c2f138efbd62bb4e7998112459177a0840c003fa8d208ad3bb2e2c94f0f04/diff:/var/lib/docker/overlay2/11a41b7bf24ea9dbd4b6a309aae1c5fdc6c484de958fa076a48b8e585caa83de/diff",
                "MergedDir": "/var/lib/docker/overlay2/f881db1dd4a4f465829fbaa43a77f4f078e22e1d16bebed707490cd80d0c7650/merged",
                "UpperDir": "/var/lib/docker/overlay2/f881db1dd4a4f465829fbaa43a77f4f078e22e1d16bebed707490cd80d0c7650/diff",
                "WorkDir": "/var/lib/docker/overlay2/f881db1dd4a4f465829fbaa43a77f4f078e22e1d16bebed707490cd80d0c7650/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
    
            "Type": "layers",
            "Layers": [
                "sha256:02c055ef67f5904019f43a41ea5f099996d8e7633749b6e606c400526b2c4b33",
                "sha256:ec5652c3523d96657d66169c0eb71b572ff065711c705a15ec02f60a21c212c3",
                "sha256:76d3e24d63f60e6a73af70be15959eb4021dd7a5a09da6925037d3b4a1673fca",
                "sha256:f281464c05be6822b95403339e2b7744fd1664e88ee9d118c7e89436ab094d58",
                "sha256:7fde79e38c038ef46904196710861e2c556363d723b8f8bf9b00369944d36aec",
                "sha256:6d4185a1708b677241d83683283c76703e788e41a2341b7c1bf4dbf12aebab45"
            ]
        },
        "Metadata": {
    
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

理解:

所有的Docker镜像都起始于一个基础镜像层,当进行或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

举一个简单地例子,假如基于Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包。

该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自镜像层的6个文件

上图中的镜像层跟之前的略有区别,主要目的是便于展示文件

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层的文件7是文件5的一个更新版本。

这种情况下,上层镜像中的文件覆盖了底层镜像层中的文件。这样就是的文件的更新版本作为一个新镜像层添加到镜像当中

Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为同一的文件系统

Linux上可用的存储引擎有AUFS、Overlay2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点

Docker在windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW[1].

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们说的容器层,容器之下的都叫镜像层!

commit镜像

docker commit 提交容器称为一个新的副本

docker commit -m="提交的描述信息" -a="作者" 容器ID 目标镜像名:[tag]

容器数据卷

什么是容器数据卷

docker的理念问题

将应用和环境打包成一个镜像!

数据?如果数据都在容器中,那么我们容器删除,数据就是丢失!需求:数据可以持久化

对于MySQL来说,容器删了,等于删库,需求:MySQL数据可以存储在本地!

容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!

这就是卷技术,说白了,就是目录的挂载,将我们容器内的目录,挂载到Linux上面!

总结一句话,就是为了容器的持久化和同步操作!容器间也是可以数据共享的

使用数据卷

方式一:直接使用命令来挂载 -v

docker run -it -v 主机目录:容器内目录

# 挂载NGINX的静态HTML文件
[root@iZwz94tkn42l6pe1uu1mqiZ home]# docker run -d --name nginx -p 3344:80 -v /home/:/usr/share/nginx/html nginx
7c49e254e17291c5c364af967329677b933015bace6911a8e048e355de8534b2

好处:我们以后修改只需要在本地修改即可,容器内会自动同步!

实战:安装MySQL

思考:MySQL的数据持久化的问题

# 获取镜像
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker pull mysql:5.7

# 运行容器,需要做数据挂载
# 安装启动MySQL,需要注意的是需要配置密码的
# 官方测试:docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

-d      后台运行
-p      端口映射
-v      卷挂载
-e      环境配置
--name  容器名字
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

具名挂载和匿名挂载

匿名挂载

-v 容器内路径!
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -d -p --name nginx01 -v /etc/nginx nginx

# 查看说是有的volume的情况
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker volume ls
DRIVER    VOLUME NAME
local     50e376e28038ef4d45c9c7b61be2fa85984577973cc150dc84ad1d9cae07425d

这种就是匿名挂载,我们在 -v 只写了容器内的路径,没有写容器外的路径!

具名挂载

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx nginx
64dc774d7bb835447e0911327f54fc3c1761a4075dd5749d9b6f31592e02486c

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker volume ls
DRIVER    VOLUME NAME
local     juming-nginx

# 通过 -v 卷名:容器内路径
# 查看一下这个卷
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker volume inspect juming-nginx
[
    {
    
        "CreatedAt": "2021-05-15T09:41:07+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]

所有的Docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxx/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载

# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载
-v 容器内路径        # 匿名挂载
-v 卷名:容器内路径    # 具名挂载
-v /宿主机的路径:容器内路径 # 指定路径股灾

拓展:

# 通过 -v 容器内领: ro | rw 改变读写权限

ro readonly  # 只读
rw readwrite # 可读可写

# 一旦设定了容器的权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx01 -v juming-nginx:/etc/nginx:rw nginx

# ro 只要看到了 ro 就说明了这个路径只能通过宿主机来操作,容器内都是无法操作

初始Dockerfile

Dockerfile就是用来构建docker镜像的构建文件!命令脚本

通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每一个命令都是一层!

# 创建一个dockerfile文件,名字可以随机,建议Dockerfile
# 文件中的内容 指令(大写)参数
FROM centos

VOLUME ["volume01","volume02"]

CMD echo "-------end-------"

CMD /bin/bash
# 这里的每个命令,就是镜像的一层
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker build -f dockerfile1 -t aa/centos:1.0 .
Sending build context to Docker daemon  57.34kB
Step 1/4 : FROM centos
latest: Pulling from library/centos
7a0437f04f83: Pull complete 
Digest: sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
Status: Downloaded newer image for centos:latest
 ---> 300e315adb2f
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in e729d405d7e1
Removing intermediate container e729d405d7e1
 ---> 9cb7e78cee19
Step 3/4 : CMD echo "-------end-------"
 ---> Running in a92b012924fc
Removing intermediate container a92b012924fc
 ---> df21671f4490
Step 4/4 : CMD /bin/bash
 ---> Running in 070dcd4c32ce
Removing intermediate container 070dcd4c32ce
 ---> 9a0c5e69eca5
Successfully built 9a0c5e69eca5
Successfully tagged aa/centos:1.0

启动自己的容器

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -it 9a0c5e69eca5 /bin/bash
[root@9b26d4a1598d /]# ls -l
total 56
lrwxrwxrwx  1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x  5 root root  360 May 15 02:16 dev
drwxr-xr-x  1 root root 4096 May 15 02:16 etc
drwxr-xr-x  2 root root 4096 Nov  3  2020 home
lrwxrwxrwx  1 root root    7 Nov  3  2020 lib -> usr/lib
lrwxrwxrwx  1 root root    9 Nov  3  2020 lib64 -> usr/lib64
drwx------  2 root root 4096 Dec  4 17:37 lost+found
drwxr-xr-x  2 root root 4096 Nov  3  2020 media
drwxr-xr-x  2 root root 4096 Nov  3  2020 mnt
drwxr-xr-x  2 root root 4096 Nov  3  2020 opt
dr-xr-xr-x 93 root root    0 May 15 02:16 proc
dr-xr-x---  2 root root 4096 Dec  4 17:37 root
drwxr-xr-x 11 root root 4096 Dec  4 17:37 run
lrwxrwxrwx  1 root root    8 Nov  3  2020 sbin -> usr/sbin
drwxr-xr-x  2 root root 4096 Nov  3  2020 srv
dr-xr-xr-x 13 root root    0 May 15 02:16 sys
drwxrwxrwt  7 root root 4096 Dec  4 17:37 tmp
drwxr-xr-x 12 root root 4096 Dec  4 17:37 usr
drwxr-xr-x 20 root root 4096 Dec  4 17:37 var
drwxr-xr-x  2 root root 4096 May 15 02:16 volume01
drwxr-xr-x  2 root root 4096 May 15 02:16 volume02

drwxr-xr-x  2 root root 4096 May 15 02:16 volume01
drwxr-xr-x  2 root root 4096 May 15 02:16 volume02

这个卷和外部一定有一个同步的目录

FROM centos
VOLUME ["volume01","volume02"] # 匿名挂载
CMD echo "-------end-------"
CMD /bin/bash

查看一下卷挂载的路径

docker inspect 容器ID
"Mounts": [
            {
    
                "Type": "volume",
                "Name": "b002d80bb17e6729578528ae73d124664d45f3619e1ae3baa2aef0b1eae28ab7",
                "Source": "/var/lib/docker/volumes/b002d80bb17e6729578528ae73d124664d45f3619e1ae3baa2aef0b1eae28ab7/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
    
                "Type": "volume",
                "Name": "7a6846ab080bf2e6b0ffb9117a2b50819dc76b396f66843a48f3efc0a31d1106",
                "Source": "/var/lib/docker/volumes/7a6846ab080bf2e6b0ffb9117a2b50819dc76b396f66843a48f3efc0a31d1106/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

数据卷容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JHyQXZr5-1623469059452)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/1621049134.jpg)]

# 启动3个容器,通过我们刚才自己写的镜像启动

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -it --name docker01 9a0c5e69eca5
[root@39b85ea978ac /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volume02
dev  home  lib64  media       opt  root  sbin  sys  usr  volume01

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -it --volumes-from docker01 --name docker02 9a0c5e69eca5
[root@39b85ea978ac /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volume02
dev  home  lib64  media       opt  root  sbin  sys  usr  volume01

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -it --volumes-from docker01 --name docker03 9a0c5e69eca5
[root@39b85ea978ac /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var	   volume02
dev  home  lib64  media       opt  root  sbin  sys  usr  volume01

# 测试:可以大会上哪壶docker01 ,查看一下docke02 和docker03是否还可以访问这个文件
# 测试依旧可以访问

多个MySQL同步数据

docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --volumes-from mysql01 --name mysql01 mysql:5.7

docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --volumes-from mysql01 --name mysql01 mysql:5.7

结论:

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止

但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的

Dockerfile

Dockerfile介绍

dockerfile是用来构建docker镜像的文件!命令参数脚本!

构建步骤:

  1. 编写一个dockerfile文件
  2. docker build 构建称为一个镜像
  3. docker run 运行镜像
  4. docker push 发布镜像(DockerHub、阿里云镜像仓库)

Dockerfile构建过程

基础知识

  1. 每个保留关键字(指令)都是必须是大写字母

  2. 执行从上到下顺序执行

  3. # 表示注释

  4. 每一个指令都会创建提交一个新的镜像层,并提交!

dockerfile是面向开发的,我们以后要发布项目的,做镜像,就需要编写dockerfile文件,这个文件十分简单!

Docker镜像逐渐成为企业的交付标准,必须要掌握!

步骤:开发,部署,运维 --------> 缺一不可

DockerFile:构建文件,定义了一切的步骤,相当于源代码

DockerImages:通过DockerFile 构建生成的镜像,最终发布和运行的产品

Docker容器:容器就是镜像运行起来提供服务器

DockerFile的指令

指令 注释
FROM 基础镜像,一切从这里开始构建
MAINTAINER 镜像是谁写的,姓名+邮箱
RUN 镜像构建的时候需要运行的命令
ADD 步骤,Tomcat镜像,这个Tomcat压缩包!添加内容
WORKDIR 镜像的工作目录
VOLUME 挂载的目录
EXPOSE 暴露端口配置
CMD 制定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT 指定这个容器启动的时候呀运行的命令,可以追加命令
ONBUILD 当构建一个被继承 DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY 类似 ADD 将我们文件拷贝到镜像中
ENV 构建的时候设置环境变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a96oOqhv-1623469059455)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515121616.png)]

列出本地进行的变更历史

# docker history 镜像ID
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker history 9a0c5e69eca5
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
9a0c5e69eca5   3 hours ago    /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/bin…   0B        
df21671f4490   3 hours ago    /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "echo…   0B        
9cb7e78cee19   3 hours ago    /bin/sh -c #(nop)  VOLUME [volume01 volume02]   0B        
300e315adb2f   5 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
<missing>      5 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      5 months ago   /bin/sh -c #(nop) ADD file:bd7a2aed6ede423b7…   209MB 

CMD和ENTRYPOINT的区别

CMD         # 制定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 
ENTRYPOINT  # 指定这个容器启动的时候呀运行的命令,可以追加命令             

CMD

# 编写 dockerfile 文件
FROM centos
CMD ["ls", "-a"]

# 构建镜像
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker build -f cmd-test -t cmdtest .

# run 运行, 发现我们的ls -a 生效了
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run df0caba05a52
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found

# 追加一个命令 -l 期待的是 ls -al
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run df0caba05a52 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.

# CMD 的情况下, -l 替换了 ["ls", "-a"]的命令, -l 不是一个命令所以报错

ENTRYPOINT

# 编写 dockerfile 文件
FROM centos
ENTRYPOINT ["ls", "-a"]

# 构建镜像
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker build -f dockerfile-cmd-entorypoint -t entrypoint-text .

# run 运行, 发现我们的ls -a 生效了
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run 5aa6363fa5f1
.
..
.dockerenv
bin
dev
etc
home
lib
lib64
lost+found

# 我们追加一个命令是直接在我们的 ENTRYPOINT 命令的后面
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run 5aa6363fa5f1 -l
total 56
drwxr-xr-x  1 root root 4096 May 15 05:47 .
drwxr-xr-x  1 root root 4096 May 15 05:47 ..
-rwxr-xr-x  1 root root    0 May 15 05:47 .dockerenv
lrwxrwxrwx  1 root root    7 Nov  3  2020 bin -> usr/bin
drwxr-xr-x  5 root root  340 May 15 05:47 dev
drwxr-xr-x  1 root root 4096 May 15 05:47 etc
drwxr-xr-x  2 root root 4096 Nov  3  2020 home
lrwxrwxrwx  1 root root    7 Nov  3  2020 lib -> usr/lib

DockerFile中很多的命令都十分的相似,我们需要了解它们的区别,我们最好的学习就是对比他们然后测试效果!

实践:Tomcat镜像

  1. 准备镜像文件 Tomcat 压缩包,JDK压缩包

    [root@iZwz94tkn42l6pe1uu1mqiZ sort]# ls -al
    total 200732
    drwxr-xr-x  2 root root      4096 May 15 14:16 .
    dr-xr-x---. 7 root root      4096 May 15 14:07 ..
    -rw-r--r--  1 root root  11496577 May  9 02:06 apache-tomcat-9.0.46.tar.gz
    -rw-r--r--  1 root root 194042837 May 15 14:16 jdk-8u202-linux-x64.tar.gz
    
    
  2. 编写dockerfile文件,官方命名 Dockerfile,build 会自动寻找这个文件,就不需要 -f 指定了

    FROM centos
    MAINTAINER 稻草人<3020139699@qq.com>
    COPY readme.txt /usr/local/readme.txt
    
    ADD jdk-8u202-linux-x64.tar.gz /usr/local/
    ADD apache-tomcat-9.0.46.tar.gz /usr/local/
    
    RUN yum -y install vim
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_202
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.46
    ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.46
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib;$CATALINA_HOME/bin
    
    EXPOSE 8080
    
    CMD /usr/local/apache-tomcat-9.0.46/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.46/bin/logs/catalina.out
    
    1. 构建镜像

      docker build -t diytomcat .
      

    我们以后开发的步骤,需要掌握Dockerfile的编写!我们之后的一切都是使用Docker镜像来发布运行!

    发布自己的镜像

    DockerHub

    1. 地址: https://hub.docker.com/ 需要有自己的账号

    2. 在我们服务器上提交自己的镜像

      [root@iZwz94tkn42l6pe1uu1mqiZ sort]# docker login --help
      
      Usage:  docker login [OPTIONS] [SERVER]
      
      Log in to a Docker registry.
      If no server is specified, the default is defined by the daemon.
      
      Options:
        -p, --password string   Password
            --password-stdin    Take the password from stdin
        -u, --username string   Username
      
      
    3. 登录完毕后就可以提交镜像了,就是一步 docker push

      # docker push 作者名/镜像名:tag标签
      
      # 示例
      docker push daocaoren/diytomcat:1.0
      

Docker网络

理解Docker0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKAzf1dg-1623469059456)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515163733.png)]

三个网络代表三个不同的环境

# docker 是如何处理容器网络访问的?
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -d -P --name tomcat01 tomcat

# 查看容器的内部网络地址 ip addr

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker exec -it tomcat01 ip addr
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
70: eth0@if71: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# Linux是否可以ping通容器内部
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# 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.090 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.061 ms
# Linux是可以ping通 docker 容器内部

原理

  1. 我们每启动一个 docke 容器,docker 就会给 docker 容器分配一个IP,我们只要安装了docker,就会有一个网卡 docker0 桥接模式,使用的技术是 evth-pair 技术

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zecVOVgk-1623469059457)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515165024.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Uzpqnoh-1623469059458)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515165217.png)]

我们发现这个容器带来网络,都是一对对的

evth-pair就是一对的虚拟设备接口,它们都是成对出现的,一端连着协议,一端彼此相连

正因为有这个特性,evth-pair充当一个桥梁,链接各种虚拟网络设备的

OpenStac, Docker容器之间的连接, OVS的连接, 都是使用 evth-pair技术

  1. 测试不同的容器之间是否可以ping通

    [root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker exec -it tomcat01 ping 172.17.0.3
    
    # 结论,容器和容器之间是可以互相ping通的
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rQsZQKCV-1623469059460)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/1621049135.jpg)]

    结论:

    所有的不同容器都是公用的一个路由器,docker0

    所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP

    小结:

    Docker 使用的是Linux的桥接, 宿主机中是一个Docker容器的网桥 docker0

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FuokTyJv-1623469059461)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/1621049136.jpg)]

Docker中的所有的网络接口都是虚拟的,虚拟的抓发效率较高(内网传递文件)

只要容器被删除了, 那么与之相对应的网络就没了

–link

思考一个场景,我们编写了一个微服务,database url=ip,项目不重启,数据库IP换掉了,我们希望可以处理这个问题,可以使用名字来进行访问容器?

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker exec -it tomcat02 ping comcat01 
ping: comcat01: Name or service not known

# 如何解决这个问题
# 通过--link 就可以解决这个问题
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
d64b68844a1da24ef8c3195dd3e6c06a0a2e183b4b5a3e68c02ad0eaa3ea5452
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.122 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.096 ms


--link 其实就是在host文件中添加了一个地址的解析

不建议使用

而默认的docker0 不支持容器名连接访问

自定义网络

查看所有的docker网络

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
83e597ad26ef   bridge    bridge    local
c126af0d2f76   host      host      local
83f0315e65a6   none      null      local

网络模式

网络名词 说明
bridge 桥接 docker(默认,自己创建的也使用bridge模式)
none 不配置网络
host 和宿主机共享网络
container 容器内网络连通(用得少,局限很大)

测试

# 我们直接启动的命令 --net bridge 在这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat

# docker0特点,默认域名不能访问 --link可以打通链接


我们可以自定义一个网络

# --driver  桥接
# --subnet  子网地址
# --gateway 网关

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
d4c462502c5eb5b9dac22f19e323920ac979f2acc773bb094afc311786bc69d9
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
83e597ad26ef   bridge    bridge    local
c126af0d2f76   host      host      local
d4c462502c5e   mynet     bridge    local
83f0315e65a6   none      null      local

我们自己的网络

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network inspect mynet
[
    {
    
        "Name": "mynet",
        "Id": "d4c462502c5eb5b9dac22f19e323920ac979f2acc773bb094afc311786bc69d9",
        "Created": "2021-05-15T17:54:19.860356594+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
    
            "Driver": "default",
            "Options": {
    },
            "Config": [
                {
    
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
    
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
    },
        "Options": {
    },
        "Labels": {
    }
    }
]

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network inspect mynet
[
    {
    
        "Name": "mynet",
        "Id": "d4c462502c5eb5b9dac22f19e323920ac979f2acc773bb094afc311786bc69d9",
        "Created": "2021-05-15T17:54:19.860356594+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
    
            "Driver": "default",
            "Options": {
    },
            "Config": [
                {
    
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
    
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
    
            "1f8a1a02d2fdec9aef59ae85fa4a9fa8b87ce53967be2be108c9b40a991088c2": {
    
                "Name": "tomcat01",
                "EndpointID": "eb29f2cd24ec1df8f35edf049a60316da7bbed9c2b1c54b63b20b74befeb0eac",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "ec2aeb7840d203896373189036a909e424ff1d4a3d4069a37afb6042a9d3abc2": {
    
                "Name": "tomcat02",
                "EndpointID": "bb2164e0e5dcaa171e7ebecf4df69d2fabdf17997629e785d53c6e290a1d2aae",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
    },
        "Labels": {
    }
    }
]

我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络

[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker exec -it tomcat01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.124 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.077 ms
^C
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.077/0.100/0.124/0.025 ms
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.082 ms
64 bytes from tomcat02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.096 ms
^C
--- tomcat02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 0.058/0.078/0.096/0.018 ms

网络连通

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zvJGGetr-1623469059463)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515180852.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y4pzdMAr-1623469059465)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515181001.png)]

测试打通 Tomcat01 到mynet

# 将一个 tomcat01 加入到 mynet 的网络中
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network connect mynet tomcat01

# 检查 mynet 的网络, 发现将 tomcat01 的容器加入直接放到了这个网络中了
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network inspect mynet
[
    {
    
        "Name": "mynet",
        "Id": "d4c462502c5eb5b9dac22f19e323920ac979f2acc773bb094afc311786bc69d9",
        "Created": "2021-05-15T17:54:19.860356594+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
    
            "Driver": "default",
            "Options": {
    },
            "Config": [
                {
    
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
    
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
    
            "650e741fac935b4163eb8a005c326855a881c377d87679fa453e74139c399d0d": {
    
                "Name": "tomcat-net-01",
                "EndpointID": "3821c1b908f2029b648bc3c78d660201245bf28bbdc6dda3ea86a1f4dc9296ef",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "d41c1e63421c3df4e983b5817109c0c4e8775ddf7505b381c9866b85fb01e645": {
    
                "Name": "tomcat01",
                "EndpointID": "405c3c313f44c0d7258bb1f757bcc9453fcb3a319d01d2e42bd1530bacbe947e",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
    },
        "Labels": {
    }
    }
]

# 测试是否可以ping通
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker exec -it tomcat-net-01 ping tomcat01
PING tomcat01 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from tomcat01.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.093 ms

Redis集群

# 创建网络
[root@iZwz94tkn42l6pe1uu1mqiZ ~]# docker network create redis --driver bridge --subnet 172.38.0.0/16

# 通过shell脚本创建六个Redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}.conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

# 通过shell脚本启动容器
for port in $(seq 1 6); \
do \
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} -v /mydata/redis/node-${port}/data:/data -v /mydata/redsi/node-${port}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${port} redis redis-server /etc/redis/redis.conf
done

企业实战

Docker Compose

简介

Docker

DockerFile build run 手动操作,单个容器

微服务。100个微服务!依赖关系。

Docker Compose 来轻松高效的管理容器。定义运行多个容器

三个步骤

Using Compose is basically a three-step process:

  1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
    • Dockerfile保证我们的项目在任何地方可以运行
  2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
    • services 什么是服务
    • docker-compose.yml 这个文件怎么写
  3. Run docker compose up and the Docker compose command starts and runs your entire app. You can alternatively run docker-compose up using the docker-compose binary.
    • 启动项目

作用:批量容器编排

Compose 是 Docker 官方的开源项目,需要安装

Dockerfile让程序咋任何地方运行。web服务,Redis、MySQL、NGINX等等多个容器

Compose

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {
    }

Compose:重要的概念

  • 服务 services:容器。应用(web、Redis、mysql。。。。)
  • 项目 project。

安装Compose

下载

curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

授权

sudo chmod +x /usr/local/bin/docker-compose

体验

官方示例:https://docs.docker.com/compose/gettingstarted/

step 1

mkdir composetest
cd composetest

创建app.py文件

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

创建requirements.txt文件

flask
redis

step2:创建Dockerfile文件

# syntax=docker/dockerfile:1
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["python", "app.py"]

step3:创建docker-compose.yml文件

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

step4:构建应用

docker-compose up

流程:

  1. 创建网络
  2. 执行 Docker-compose.yaml
  3. 启动服务

Docker-compose.yaml

Creating composetest_web_1 … done
Creating composetest_redis_1 … done

默认的服务名 文件名 _ 服务名 _ num

未来可能有多个服务器,集群

网络规则

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dwkLuHTH-1623469059466)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515224839.png)]

例如:10个服务 => 项目(项目中的内容都在同个网络下。可以进行域名访问)

例如: mysql:3306

10个容器实例都是MySQL

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BHFYe1EA-1623469059468)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515225226.png)]

如果在同一个网络下,我们可以直接通过域名访问

停止: docker-compose down

Docker小结

  1. Docker镜像。run => 容器
  2. DockerFile 构建镜像(服务打包)
  3. docker-compose启动项目(编排、多个微服务环境)
  4. Docker网络

yaml规则

docker-compose.yaml 是核心

官网地址:https://docs.docker.com/compose/compose-file/compose-file-v3/

version: "" # 版本
services: # 服务
  服务1:web
  服务2:Redis

项目依赖的启动顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S05cwzs8-1623469059469)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210515231207.png)]

项目要重新部署打包

docker-compose up --build  #重新部署打包

Docker Swarm

购买服务器

4台阿里云服务器,建议使用按量付费,1核2G的配置

工作模式

Docker Engine 1.12 introduces swarm mode that enables you to create a cluster of one or more Docker Engines called a swarm. A swarm consists of one or more nodes: physical or virtual machines running Docker Engine 1.12 or later in swarm mode.

There are two types of nodes: managers and workers.

Swarm mode cluster

If you haven’t already, read through the swarm mode overview and key concepts.

搭建集群

docker swarm --help

[root@iZ2vc1rk4i9i8i1z7q92wxZ ~]# docker swarm --help

Usage:  docker swarm COMMAND

Manage Swarm

Commands:
  ca          Display and rotate the root CA
  init        Initialize a swarm
  join        Join a swarm as a node and/or manager
  join-token  Manage join tokens
  leave       Leave the swarm
  unlock      Unlock swarm
  unlock-key  Manage the unlock key
  update      Update the swarm

Run 'docker swarm COMMAND --help' for more information on a command.

初始化节点

docker swarm init

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cJJ3Fy4Q-1623469059472)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516093222.png)]

docker swarm join 加入一个节点

# 获取令牌
docker swarm join-token manager # 角色1
docker swarm join-token worker  # 角色2

加入一个节点worker

# 通过令牌生成一个worker 节点
# docker swarm join-token worker
[root@iZ2vc1rk4i9i8i1z7q92wzZ ~]# docker swarm join --token SWMTKN-1-3xy7x0ygn751grv4ierl11c3ktq1v6y41744vaukkco88x608r-15fufl7g1kjuyhgk5f8h7pngt 172.22.9.93:2377
This node joined a swarm as a worker.

加入一个节点manager

[root@iZ2vc1rk4i9i8i1z7q92wxZ ~]# docker swarm join --token SWMTKN-1-3xy7x0ygn751grv4ierl11c3ktq1v6y41744vaukkco88x608r-9eqp8d46za5gx07bnri6aci0g 172.22.9.93:2377
This node joined a swarm as a manager.

集群节点要保证manager节点为单数,至少是3个

Raft协议

保证大多数节点存活,才可以使用,高可用!

当前共有两个manager节点,关闭了一台服务器后,直接报错

[root@iZ2vc1rk4i9i8i1z7q92wxZ ~]# docker node ls
Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded

重启manager节点服务器后,集群有重新选举了一个新的leader

重选前的leader

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-atzkn3Do-1623469059473)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516102003.png)]

重选后的leader

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tFwiWhAr-1623469059475)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516101818.png)]

移除一个worker节点后,集群服务继续存活

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GOySPeXQ-1623469059476)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516102221.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YiJwz5pL-1623469059477)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516102305.png)]

我们可以将此移除的worker节点加入到manager节点,此时我们已经有了3台manager管理节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zL0shQ5R-1623469059479)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516102512.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lZOLNaEf-1623469059480)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516102546.png)]

使用Swarm

弹性、扩缩容、进群

以后告别docker run

docker-compose up 启动一个项目,单机

集群:swarm docker service

容器 => 服务

容器 => 服务 => 副本

容器 => 服务 => 副本(同时开启10个Redis容器)

体验

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XR9Ea7NB-1623469059481)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516103705.png)]

灰度发布 = 金丝雀发布

创建服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FPi4sxJX-1623469059483)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516103938.png)]

docker run # 容器启动, 不具有扩缩容器
docker service # 服务,具有扩缩容器,滚动更新

更新服务数量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2fJv7ZVV-1623469059485)(https://raw.githubusercontent.com/zhusli2013you/image/master/data/20210516104645.png)]

概念总结

swarm

集群的管理和编排,docker可以初始化一个swarm集群,其他节点可以加入,(管理、工作者)

Node

就是一个docker节点。多个节点就组成了一个网络集群(管理、工作者)

Service

任务,可以在管理节点或者工作节点来运行,核心

Task

容器内的命令

CI\CD Jenkins

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhusli2013you/article/details/117842421

智能推荐

前端开发之vue-grid-layout的使用和实例-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏34次。vue-grid-layout的使用、实例、遇到的问题和解决方案_vue-grid-layout

Power Apps-上传附件控件_powerapps点击按钮上传附件-程序员宅基地

文章浏览阅读218次。然后连接一个数据源,就会在下面自动产生一个添加附件的组件。把这个控件复制粘贴到页面里,就可以单独使用来上传了。插入一个“编辑”窗体。_powerapps点击按钮上传附件

C++ 面向对象(Object-Oriented)的特征 & 构造函数& 析构函数_"object(cnofd[\"ofdrender\"])十条"-程序员宅基地

文章浏览阅读264次。(1) Abstraction (抽象)(2) Polymorphism (多态)(3) Inheritance (继承)(4) Encapsulation (封装)_"object(cnofd[\"ofdrender\"])十条"

修改node_modules源码,并保存,使用patch-package打补丁,git提交代码后,所有人可以用到修改后的_修改 node_modules-程序员宅基地

文章浏览阅读133次。删除node_modules,重新npm install看是否成功。在 package.json 文件中的 scripts 中加入。修改你的第三方库的bug等。然后目录会多出一个目录文件。_修改 node_modules

【】kali--password:su的 Authentication failure问题,&sudo passwd root输入密码时Sorry, try again._password: su: authentication failure-程序员宅基地

文章浏览阅读883次。【代码】【】kali--password:su的 Authentication failure问题,&sudo passwd root输入密码时Sorry, try again._password: su: authentication failure

整理5个优秀的微信小程序开源项目_微信小程序开源模板-程序员宅基地

文章浏览阅读1w次,点赞13次,收藏97次。整理5个优秀的微信小程序开源项目。收集了微信小程序开发过程中会使用到的资料、问题以及第三方组件库。_微信小程序开源模板

随便推点

Centos7最简搭建NFS服务器_centos7 搭建nfs server-程序员宅基地

文章浏览阅读128次。Centos7最简搭建NFS服务器_centos7 搭建nfs server

Springboot整合Mybatis-Plus使用总结(mybatis 坑补充)_mybaitis-plus ruledataobjectattributemapper' and '-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏3次。前言mybatis在持久层框架中还是比较火的,一般项目都是基于ssm。虽然mybatis可以直接在xml中通过SQL语句操作数据库,很是灵活。但正其操作都要通过SQL语句进行,就必须写大量的xml文件,很是麻烦。mybatis-plus就很好的解决了这个问题。..._mybaitis-plus ruledataobjectattributemapper' and 'com.picc.rule.management.d

EECE 1080C / Programming for ECESummer 2022 Laboratory 4: Global Functions Practice_eece1080c-程序员宅基地

文章浏览阅读325次。EECE 1080C / Programming for ECESummer 2022Laboratory 4: Global Functions PracticePlagiarism will not be tolerated:Topics covered:function creation and call statements (emphasis on global functions)Objective:To practice program development b_eece1080c

洛谷p4777 【模板】扩展中国剩余定理-程序员宅基地

文章浏览阅读53次。被同机房早就1年前就学过的东西我现在才学,wtcl。设要求的数为\(x\)。设当前处理到第\(k\)个同余式,设\(M = LCM ^ {k - 1} _ {i - 1}\) ,前\(k - 1\)个的通解就是\(x + i * M\)。那么其实第\(k\)个来说,其实就是求一个\(y\)使得\(x + y * M ≡ a_k(mod b_k)\)转化一下就是\(y * M ...

android 退出应用没有走ondestory方法,[Android基础论]为何Activity退出之后,系统没有调用onDestroy方法?...-程序员宅基地

文章浏览阅读1.3k次。首先,问题是如何出现的?晚上复查代码,发现一个activity没有调用自己的ondestroy方法我表示非常的费解,于是我检查了下代码。发现再finish代码之后接了如下代码finish();System.exit(0);//这就是罪魁祸首为什么这样写会出现问题System.exit(0);////看一下函数的原型public static void exit (int code)//Added ..._android 手动杀死app,activity不执行ondestroy

SylixOS快问快答_select函数 导致堆栈溢出 sylixos-程序员宅基地

文章浏览阅读894次。Q: SylixOS 版权是什么形式, 是否分为<开发版税>和<运行时版税>.A: SylixOS 是开源并免费的操作系统, 支持 BSD/GPL 协议(GPL 版本暂未确定). 没有任何的运行时版税. 您可以用她来做任何 您喜欢做的项目. 也可以修改 SylixOS 的源代码, 不需要支付任何费用. 当然笔者希望您可以将使用 SylixOS 开发的项目 (不需要开源)或对 SylixOS 源码的修改及时告知笔者.需要指出: SylixOS 本身仅是笔者用来提升自己水平而开发的_select函数 导致堆栈溢出 sylixos

推荐文章

热门文章

相关标签