docker入门
FROM
B站-遇见狂神说 https://www.bilibili.com/video/BV1og4y1q7M4?p=27&spm_id_from=pageDriver
docker安装
虚拟化的容器技术,轻巧,快速,方便
可以理解为:一种带环境的程序集合;
配置好的docker环境可以放到别的机器上,不用担心因为环境问题而无法运行。
在docker之前,都是用虚拟机技术,windows上安装Vmware,在Windows电脑上模拟出一台或多台电脑,十分笨重卡;
docker上运行的容器,例如centos,都是精简版的,所以小,其只包含了一些基本命令,根本的信息还是使用的主机的系统,所以启动的快;
安装docker
安装docker有不同类型 install on centos; install on Ubuntu等,具体安装什么环境看官方文档
本文档已Centos7为例
需要存在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
2.安装一些需要的安装包(环境)
yum install -y yum-utils
3.设置镜像仓库
# 官方文档提供的是国外的镜像仓库,速度很慢,此处不建议用
# 不用这个 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
4.安装最新版docker引擎
# 安装引擎前,更新软件包索引
yum makecache fast
# docker-ce 表示社区版(推荐) ee 表示企业版
yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
5.可以启动docker、测试docker了
# 一般没报错,就是启动成功了
systemctl start docker
docker version
# docker的运行命令都有run
# 运行hello-world 镜像,他会去远程拉去该镜像
docker run hello-world
6.查看一下镜像在否
# images 命令
docker images
卸载docker
# 卸载当前依赖
yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 删除docker资源、一般都是这个默认工作路径
rm -rf /var/lib/docker
7.阿里云镜像加速
登陆阿里云-工作台-容器镜像服务-镜像工具-镜像加速器-centos
配置镜像加速器
针对Docker客户端版本大于 1.10.0 的用户
# 复制直接跑
您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://1907i166.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
8. docker run工作原理
运行yuge这个镜像
docker run yuge
1.查找本地是否存在这个镜像,如果存在,直接运行
不存在 那就去远程docker仓库获取(默认docker hub,自己有配置阿里云镜像或者别的什么镜像仓库)
2.远程仓库找到了,下载到本地运行
远程仓库没找到,直接报错
9.docker简单工作原理
服务器上运行docker程序,相当于在我们服务器上运行了个小的且隔离的服务器,与整个服务器隔离开互不影响。
因此我们web程序访问docker上的nginx、mysql等应用,需要进行建立连接:整个Linux系统与docker的连接.
10.docker为什么比虚拟机快
百度去
docker_portainer安装
# 拉去镜像
docker search portainer
docker pull portainer/portainer
# portainer_data这个挂载是我自己建的一个卷,后面那个什么.sock是单机启动必须指定docker.sock
docker run -d --name portainer --restart always -p 8092:9000 -v portainer_data:/data -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
docker常用命令
官方命令文档:https://docs.docker.com/engine/reference/commandline
1.帮助命令
# 版本
docker version
# 详细信息:服务器信息、镜像信息、运行状态信息
docker info
# 帮助命令
docker --help
docker images --help
2.镜像命令
# 显示全部镜像
docker images -a
# 显示镜像的id
docker images -q
docker images -aq 或者 -qa 都可以
# 搜索命令
docker search mysql
# 过滤搜索 --filter
# 过滤掉MySQL星标小于500的
docker search mysql --filter stars=500
# 镜像下载
docker pull
# 默认下载最新版本
docker pull mysql
# 指定版本下载,这个版本一定要在官方文档支持的
docker pull mysql:5.7
# 删除镜像 remove image + 指定容器id + id + id 多个删除
docker rmi id id id
# 全部删除镜像 $(这里面是镜像id列表)
docker rmi -f $(docker images -aq)
3.容器命令
有镜像才可以创建容器
# 启动容器 docker run 参数 image
# 参数说明
# --name="name" 容器名字
# -d 以后台方式运行
# -it 使用交互方式运行,进入容器查看内容
# -P 大写的P,指定容器的端口,灰常重要
# -p ip:8080:8080 主机端口映射到容器端口(常用)
# -p 8080:8080 主机端口映射到容器端口(常用)
# -p 8080 容器端口
# -p 小写的p,随即指定端口
# 启动并进入容器
docker run -it centos /bin/bash
[root@iZ2zec82iqaelrhwpp07m4Z ~]# docker run -it centos /bin/bash
[root@c09aff7abbd9 /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
启动并进入发现里面就是个小型的centos系统,very good
# 容器停止并退出 在容器内直接exit
exit
# 容器退出不停止 Ctrl + p + q
# 列出容器 ps
docker ps 列出正在运行的容器
docker ps -a 列出全部的容器
docker ps -n=5 最近5个容器
docker ps -aq 列出全部容器id
docker ps -n=2 -q
# 删除容器
docker rm 容器id,正在运行的容器没办法删除
docker rm -f 可以删除正在运行的容器
docker rm -f $(docker ps -aq)
# 启动、重启、停止正在运行的、强制停止
docker start 容器id
docker restart id
docker stop id
docker kill id
常用命令
# 后台启动
docker run -d centos
# 坑 docker ps 发现没有在运行
# 因为:docker检测到我们启动的容器并没有对外提供什么服务,所以启动完了他就自动停止了,使用run -it 启动就不会出现此坑
# 查看日志命令(容器启动才有用)
docker logs -f -t --tail 10 容器id
# 查看进程信息
docker top 容器id
# docker inspect 查看容器内部信息
docker inspect 容器id
# 进入当前正在运行的容器
# -it 表示以交互模式运行
docker exec -it 容器id /bin/bash
docker attach 容器id
# exec 与 attach 区别
# exec: 进入容器后新开启一个终端,可以在里面进行操作(常用)
# attach: 直接进入正在执行的终端,不会启动新的进程
# docker cp 容器内-文件拷贝到主机
docker cp 容器id:容器内路径 主机路径
# 主机-文件拷贝到容器内 使用挂载
# 查看docker服务器信息
docker stats
# 查看镜像如何做的
docker history 镜像id
docker history --no-trunc 镜像id
# 给镜像打标签(重命名) + 版本号
docker tag 镜像id mytomcat/镜像名:1.0
# docker 保存tar包、导入tar包
docker save -o mytomcat.tar mytomcat # 保存当前镜像到当前目录为mytomcat.tar
docker load -i mytomcat.tar # 将当前目录的这个tar包导入进容器镜像中
测试拉取镜像、启动镜像nginx
# -p 暴露端口
# docke run -d --name nginx01 -p 3333:8080 nginx
# curl 3333 本机自测这个端口
提交镜像
# commit 提交容器+镜像 成为新的镜像 方便使用
# docker commit -m="描述" -a="xingyu" 容器id 要生成名字:标签
docker commit -m="nginx配置好的镜像" -a="yuge" 5091f3c823ca nginx01:1.0.1
[root@iZ2zec82iqaelrhwpp07m4Z /]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx01 1.0.1 58e14049e3b5 4 seconds ago 141MB
nginx latest 605c77e624dd 4 months ago 141MB
tomcat latest fb5657adc892 4 months ago 680MB
容器数据卷(数据持久化)
容器间数据共享技术:目录的挂载,讲容器内的目录挂载到主机上;
# 直接使用命令挂载 -v 主机目录:容器目录 -v 可以挂载多个
# 当容器启动成功后,挂载成功,主机目录就与容器目录的内容双向绑定,自动同步
# 只要容器建立,停止容器也不会影响
docker run -d -v /home/ceshi:/home -v 目录:目录 -v 目录:目录 centos /bin/
docker run -it --name nginx03 -p 8094:80 -v /home/ceshi:/home nginx /bin/bash
# 删除、编辑主机目录信息,容器内目录信息也会删除、编辑;但是删除容器目录信息,主机的不会被删除
mysql 容器注意事项
- -e 命令 MySQL的初始密码
具名挂载、匿名挂载
匿名挂载:容器启动时只指定了容器内挂载(卷)的路径,未指定主机路径(卷);
具名挂载:容器启动时只制定了容器内的挂载路径,并且为卷赋名;
# 匿名挂载 只指定了容器内路径
docker run -d *** -v /etc/nginx nginx /bin/bash
# 查看卷(挂载)
docker volume ls
# 通过卷id查看挂载目录
docker volume inspect 卷id
# 具名挂载 指定了卷的名称 方便查找
# -v的冒号前面字符未加根目录'/',表示这个是名称,即具名
docker run -d *** -v juming:/etc/nginx nginx /bin/bash
挂载的三种方式
1. 匿名挂载
docker run *** -v /容器内路径 /bin/bash
2. 具名挂载
docker run *** -v 卷名:/容器内路径
3. 正常挂载
docker run *** -v /主机路径:/容器路径
挂载时加上权限
# :ro 只读 :rw 可读可写 支持三种挂载方式
1.docker run -v /home:/home:ro /bin/bash
# 表示只读,要想修改这个容器路径内的信息,只能修改宿主机的挂载路径信息
2. docker run -v name:/home:rw /bin/bash
# 表示可读可写,容器路径内信息可以直接修改,无需通过宿主机挂载路径修改,不过常用的话还是改宿主机信息方便
Dockerfile(大写D小写f)
用来构建docker镜像的文件,命令脚本
docker的镜像是一层一层的,因此dockerfile文件命令也是一层一层的,每个命令是一层;
# 简单的构建一个dockerfile文件(没有后缀)
FROM centos
VOLUME ["volumn1","volumn2"]
CMD echo "----END----"
CMD /bin/bash
# 构建镜像命令
# -f 表示引用那个dockerfile;dockerfile文件名如果叫做dockerfile1等等,那一定要在构建时指定绝对路径
# 只有在叫Dockerfile时,并且在当前目录构建,才不需要指定绝对路径
# -t target的意思:新的镜像名称 可以加':1.0',表示tags为1.0版本
# . 最后的那个'.'不能忘记
docker build -f /home/dockerfile -t yugecentos .
# 标准官方名字文件可以直接当前路径构建
docker build -t myimages .
# 构建完成启动下自己的镜像
docker run -d -it yugecentos /bin/bash
# 新启动的容器内就会有我们要的两个 挂载卷目录 volumn1,volumn2
# 查看容器的信息,找到"Mounts",就可以看到挂载的信息了
docker inspect 容器id
# 在配置镜像时,没有 VOLUMN ["volumn1"] 挂载镜像,那还是在启动阶段 -v命令手动挂载
docker run -d -v volumn1:/容器内路径 yugecentos
数据卷容器
例:多个MySQL需要数据共享;
# -e 命令,设置环境,此处就是设置MySQL的初始密码
docker run -e MYSQL_ROOT_PASSWORD=123456
# 多个挂载放在一起:挂载再进行挂载,都是允许的,文件互相同步
# 实现多个容器信息同步:配置文件、数据等的共享,知道没有容器使用,数据卷才会结束,
docker run -d --name nginx02 --volumes-from nginx01 nginx
docker run -d --name nginx03 --volumes-from nginx01 nginx
数据卷总结
1.数据卷的声明周期:只有存在一个容器在使用,则一直存在。
2.多个容器进行数据共享时,删除任意一个并不会影响,但是全部删除了,拿数据就会消失;
因此,为了保证我们数据的安全,还是需要将其中一个容器挂载到主机服务器,这样就算容器全部删除,数据还会 保存。
dockerfile
构建docker镜像的文件:命令脚本的集合;
构建步骤:
1、编写dockerfile 文件
2、docker build 构建一个镜像
3、docker run 运行镜像
4、docker push 发布镜像(远程仓库)
dockerfile介绍
1、指令的关键字必须大写字母
2、执行顺序从上到下
3、每个指令都会创建提交一个新的镜像层,并提交
# FROM 基础镜像,字面意思:来源
FROM
# MAINTAINER 作者 一半格式为 作者+邮箱
MAINTAINER
# RUN 运行时的命令
RUN
# ADD 添加的东西,比如想要在镜像里面添加的内容,比如tomcat安装包
ADD
# WORKDIR 镜像的工作目录
WORKDIR
# 卷,挂载主机的位置
VOLUME
# 对外指定的端口(暴露哪个端口)
EXPOSE
# 运行
RUN
# CMD 指定容器启动时要运行的命令
CMD
# ENTRYPOINT(追加命令) 同CMD 一样,指定需要运行的命令;
ENTRYPOINT
# ONBUILD 当继承一个 dockerfile时候,会触发
ONBUILD
# COPY 复制,类似add命令,将文件拷贝到镜像中
COPY
# 环境,构建时设置环境变量 后面跟键值对的形式
ENV
Dockerfile 构建tomcat
1、建立Dockerfile文件
# 基于centos镜像
FROM centos
# 作者
MAINTAINER yuge<738524794@qq.com>
# 将Dockerfile文件拷贝到镜像中,我自己试的时候,只能指定相对路径,绝对路径会报错找不到文件
COPY Dockerfile /usr/local/Dockerfile
# 添加tomcat(需要jdk)和jdk,安装包和Dockerfile同一路径,自动解压到指定目录下
ADD jdk-8u333-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.79.tar.gz /usr/local/
# 添加个vim命令,因为centos的基础镜像包没有这个命令
# RUN yum -y install vim 因为centos版本问题这行命令会报错
# 配置工作默认镜像进来时候的目录,即配置环境
ENV MYPATH /usr/local
WORKDIR $MYPATH
# 配置java\tomcat的环境
ENV JAVA_HOME /usr/local/jdk1.8.0_333
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools/jar
ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.79
ENV CATALINA_BASH /usr/local/apache-tomcat-8.5.79
ENV PATH $PATH:$JAVA_HOME/lib:$CATALINA_HOME/lib:$CATALINA_HOME/bin
# 因为tomcat默认端口8080,那就把8080暴露出去
EXPOSE 8080
# 启动时,需要执行的命令 用and符号连接起来‘&&’
CMD /usr/local/apache-tomcat-8.5.79/bin/startup.sh && tail -F /usr/local/apache-tomcat-8.5.79/bin/logs/catalina.out
2、建镜像
# 官方名字因此不用指定Dockerfile
docker build -t mytomcat .
3、启动镜像
# 启动自己的镜像 映射端口 挂载目录
docker run -d --name yugetomcat -p 8090:8080 -v /home/volume/tomcat/project:/usr/localapache-tomcat-8.5.79/webapps/ -v /home/volume/tomcat/logs:/usr/localapache-tomcat-8.5.79/logs mytomcat:latest
4、检查下
docker exec -it id /bin/bash
# 使用 ls 命令发现当前路径就是我们再 Dockerfile中指定的WORKDIR
# 可以浏览器访问tomcat了
发布镜像到Dockerhub
# 肯定要注册自己的DockerHub账号的,然后直接在服务器上提交就好
# 用户名
docker login --username=xingyu555 registry.cn-hangzhou.aliyuncs.com
# docker登录
docker login -u 你的名字 -p 你的密码
# 提交hub
docker push 我得镜像名:1.0
发布到阿里云镜像hub
# 发布
登录阿里云
docker login --username=xingyu555 registry.cn-beijing.aliyuncs.com
创建命名空间
创建镜像仓库,不要覆盖了别的镜像
推送镜像(仓库信息里面有命令:格式如下)
docker login --username=xingyu555 registry.cn-beijing.aliyuncs.com
docker tag [ImageId] registry.cn-beijing.aliyuncs.com/xingyu555/yuge:[镜像版本号]
docker push registry.cn-beijing.aliyuncs.com/xingyu555/yuge:[镜像版本号]
拉取镜像
docker pull registry.cn-beijing.aliyuncs.com/xingyu555/yuge:[镜像版本号]
docker网络
容器没有ping命令的话,可以进入容器内部进行更新
apt-get update
apt install iputils-ping
docker0
[root@iZ2zec82iqaelrhwpp07m4Z project]# 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:0a:00:f2 brd ff:ff:ff:ff:ff:ff
inet 172.25.88.13/20 brd 172.25.95.255 scope global dynamic eth0
valid_lft 311155183sec preferred_lft 311155183sec
# 172.25.88.13 阿里云内网地址
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:a5:c9:fa:a2 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
# 172.17.0.1 docker0地址,可以当成路由器地址,安装docker后就会生成一个
# 启动一个容器后,再看网络信息
[root@iZ2zec82iqaelrhwpp07m4Z project]# 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:16:3e:0a:00:f2 brd ff:ff:ff:ff:ff:ff
inet 172.25.88.13/20 brd 172.25.95.255 scope global dynamic eth0
valid_lft 311153432sec preferred_lft 311153432sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:a5:c9:fa:a2 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
# 这个113 112 就是新启动的容器的一对网卡(容器的网卡是成对出现的)veth-pair技术:虚拟接口
113: veth754988b@if112: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 32:93:98:ac:e6:f5 brd ff:ff:ff:ff:ff:ff link-netnsid 0
evth-pair 作为主机与容器的通信桥梁,连接各种虚拟设备
# 查看容器ip networks
docker inspect tomcat01
# 因为版本问题 下面这条命令可能无法执行
docker exec -it tomcat01 ping 容器ip
主机与容器之间可以ping通,容器容器之间也可以ping通(通过主机docker),安装docker后相当于安装了一个路由器,每启动一个容器,就会分配一个ip,所以都可以互通(veth-pair技术)。
docker link
# tomcat03 link 上 tomcat01
docker run -it --name tomcat03 --link tomcat01 /bin/bash
# 查看docker网络
docker netwokr ls
docekr inspect id
# 进入容器查看容器 网络绑定信息
# 上面我们用tomcat03 link了 tomcat01
docker exec -it tomcat03 cat /etc/hosts
docker exec -it tomcat03 /bin/bash
cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 tomcat01 6e92e69b7491 # 这就是绑定的tomcat01
172.17.0.4 ef32788a846e # 这个是docker分配给容器的虚拟ip
# 这时在容器里面ping tomcat01 就可以通了
root@ef32788a846e:/usr/local/tomcat# ping tomcat01
bash: ping: command not found # 没有ping的命令,请自行百度处理
link本质:host映射,已经不建议使用了;使用自定义网络,不适用docker0,因为他不支持容器名访问。
自定义网络
使用桥接模式网络 bridge
docker network ls
NETWORK ID NAME DRIVER SCOPE
384a4e3961b5 bridge bridge local
a5bbb4302ec2 host host local
573ce6bbbe7a none null local
# 我们正常的启动容器时,没有指定网络,其实是有默认使用bridege-docker0的(无法访问域名)
# 下面这俩相等
docker run -it tomcat01 tomcat /bin/bash
docker run -it tomcat01 --net bridge tomcat /bin/bash
创建网络
# 创建
docker network create --help
# --driver bridge 桥接网络
# --subnet 192.168.0.0/16 子网掩码、数量 下面可以绑定网络为 192.168.0.2 到 192.168.255.255 好多个
# --gateway 192.168.0.1 网关ip
# mynet 随便起的网络名称
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
将tomcat发布在自己建立的网络中
# 指定网络,不适用默认网络
docker run -it -d --name tomcat01 --net mynet tomcat /bin/bash
docker run -it -d --name tomcat02 --net mynet tomcat /bin/bash
docker inspect mynet
docker exec -it tomcat01 ping tomcat02 是可以ping的通的
# 现在就不需要进行--link了,就可以容器之间相互ping了,只要在同一网络下
# 不在同一个网络下,ping 不通的
docker network create --driver bridge --subnet 192.167.0.0/16 --gateway 192.168.0.1 mynet2
docker run -it -d --name tomcat03 --net mynet2 tomcat /bin/bash
# 用mynet的容器去ping mynet2的容器 是ping不通的
docker exec -it tomcat01 ping tomcat03 不通
docker网络互通
不通网络间,我们通常把redis集群放在一个网络,mysql集群放在一个网络,分网络管理;
但是这样会导致redis无法访问mysql,因此需要进行网络打通 --connect
# 我现在有两个网络mynet、mynet2
# mynet上面有tomcat01 ,mynet2上面有tomcat03
# 网络打通
docker network connect mynet2 tomcat01 # 然后再用tomcat01 ping tomcat03 就可以了
# 将tomcat01放到了mynet2网络中了
网络打通后看看网络怎么变成什么了
docker inspect tomcat01
# docker inspect mynet2
# 展示
"Networks": {
"mynet": { # 原tomcat01属于mynet网络的
"IPAMConfig": null,
"Links": null,
"Aliases": [
"a537269d7dd8"
],
"NetworkID": "a4275f1352244bb68b9e8d70ecc9f581a929b14bb4488c423229ac0e2eb02163",
"EndpointID": "43c2760be9aedb01603b6e4b69a0c4bc2586545754aa61008d8374cb887506ba",
"Gateway": "192.168.0.1",
"IPAddress": "192.168.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a8:00:02",
"DriverOpts": null
},
"mynet2": { # 现在tomcat01 也存在mynet2中了
"IPAMConfig": {},
"Links": null,
"Aliases": [
"a537269d7dd8"
],
"NetworkID": "733c3cd12346a201865c6dc3daf10b83e349e499364b695a7960b56f3f80b180",
"EndpointID": "474cb493b396b68f3409e1a48b8ee01b4ae99b856b038265c54bfc96317d880f",
"Gateway": "192.167.0.1",
"IPAddress": "192.167.0.3", # 并且占用了mynet2中的一个ip
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a7:00:03",
"DriverOpts": {}
}
现在tomcat01存在了两个ip,mynet中一个,mynet2中一个;
一个容器多个ip;
针对容器与网络,多个容器需要挨个打通;
docker compose
管理多容器的工具,不需要每个容器都单独的构建启动。
根据配置文件进行批量容器编排。
1、需要一个Dockerfile文件
2、docker-compose.yml文件
3、启动、停止项目
安装compose
# 官网下载
curl -SL https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
# 官网地址下载太慢,可以考虑百度下搜索别的
# 授权
chmod 777 docker-compose
# 测试,显示版本号就安装成功了
docker-compose version
官网简单实现测试
https://docs.docker.com/compose/gettingstarted/
1、创建目录
mkdir composetest
2、创建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)
3、创建另一个名为的文件requirements.txt
flask
redis
4、创建Dockerfile
- 从 Python 3.7 映像开始构建映像。
- 将工作目录设置为
/code
. - 设置命令使用的环境变量
flask
。 - 安装 gcc 和其他依赖项
- 复制
requirements.txt
并安装 Python 依赖项。 - 向镜像添加元数据以描述容器正在侦听端口 5000
- 将项目中的当前目录复制
.
到镜像中的workdir.
。 - 将容器的默认命令设置为
flask run
.
# 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 ["flask", "run"]
5、在 Compose 文件中定义服务、创建一个名为的文件docker-compose.yml
后缀名为 .yaml 更规范,优先级更高
version: "3.9" # 声明版本
services: # 服务
web: # 服务一
build: . # 这个'.'表示需要根据同目录下的Dockerfile文件自己构建镜像
ports:
- "8000:5000" # 端口映射
redis: # 服务二
image: "redis:alpine" # 从官方拿精简版镜像
这个 Compose 文件定义了两个服务:web
和redis
.
该服务使用从当前目录中web
构建的图像。Dockerfile
然后它将容器和主机绑定到暴露的端口,8000
. 此示例服务使用 Flask Web 服务器的默认端口,5000
.
该redis
服务使用 从 Docker Hub 注册表中提取的公共Redis映像。
6、使用 Compose 构建并运行您的应用程序
# 通过compose启动,会生成自己的网络,可以瞧瞧 docker network ls
docker-compose up
7、测试
# 启动成功后测试下,调的通就行
curl localhost:8000
# 关闭服务
docker-compose stop
# 后台启动
docker-compose up -d
8、网络的高可用
docker network ls
"Containers": {
"72d014f5ad025c11ac8a4e4438457668cd56577b5987a927fcc1dba7ddc0e883": {
"Name": "composetest-redis-1",
"EndpointID": "2bb814aaf216f658d4a7bb221c9e79b6886031267ca0de7495383a50c27ebad7",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"fe544716c7e2cb00272cf75abeb4c56b5e4b28e023028347b3f41a1d6e2ffa0d": {
"Name": "composetest-web-1",
"EndpointID": "f3c7a815b50f493f15fbc9030ebbd5d1db7bbcdcbd88c4a4dba99dd3d04502a7",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
通过compose启动的容器,全部在同一个网络下,因此各个容器间可以直接通过 域名:端口 进行访问,
比如访问redis, 就可以 'redis:6379' 即可
docker-compose 命令必须在docker-compose.yml 同级目录使用
优点:一个命令启动、停止配置文件内的所有容器;
docker-compose.yml编写规则核心
官方文档(太多了):https://docs.docker.com/compose/compose-file/
CSDN大佬:https://blog.csdn.net/huangjinjin520/article/details/124054043
# 主要三层
1.version: # compose版本,与docker版本是向下兼容的,推荐使用最新的版本,当然docker也是最新版本优先
2.services: # 应用服务信息,即镜像容器相关(第三层都是第二层指向过去的)
3.networks: # 网络配置
volumes: # 挂载卷配置
configs: # 用来配置每个服务的方位config的权限
secrets: # 对每个数据授予对保密数据的访问权限
...
使用docker官方提供的wordpress博客简易测试
官方提供:https://docs.docker.com/samples/wordpress/
1、创建一个空文件夹
mkdir mywordpress
2、创建docker-compose.yaml文件
version: "3.9" # 使用3.9版本compose
services: # 服务应用
db: # 数据库
image: mysql:5.7 # 镜像版本
volumes:
- db_data:/var/lib/mysql # 挂载卷
restart: always
environment: # 环境设置
MYSQL_ROOT_PASSWORD: somewordpress # 设置root用户密码
MYSQL_DATABASE: wordpress # 数据库名称
MYSQL_USER: wordpress # 数据库用户
MYSQL_PASSWORD: wordpress # 数据库密码
wordpress: # 应用
depends_on: # 依赖
- db # 依赖db,启动本应用之前会先去启动db服务
image: wordpress:latest # 镜像
volumes:
- wordpress_data:/var/www/html # 卷
ports:
- "8000:80" # 映射暴露端口
restart: always
environment:
WORDPRESS_DB_HOST: db # 指向域名:因为docker-compose启动的服务都在同一个网络下面
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
wordpress_data: {}
3、后台启动
docker-compose up -d
4、over
总结
1、我们需要一个应用,此例中的app.py
2、需要一个Dockerfile 文件用打包应用、构建镜像
3、需要一个Docerk-compose.yml文件定义整个服务,环境
4、docker-compose up 启动项目
docker swarm
集群部署
搭建集群
1、一台服务器init,初始化一个集群主机;
2、这个集群主机提供 manager token、worker token;
3、其他manager、worker服务器通过token加入集群;
# 集群的几个服务器互相网络相同,同一个子节点下,(我试了下ping通了,但是docker集群无法搭建)
# 首先生成一个集群的主节点(定义集群的开始) - 本机的ip
docker swarm init --advertise-addr 172.17.***.***
[root@iZ7xva6bpev0ngkpysg7l1Z ~]# docker swarm init --advertise-addr 172.17.***.***
Swarm initialized: current node (h00kcv542j0rrtl44cdod976n) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0jeioqc0ll53saqzwf0a4pj8if1lwwqxecdi3vsrddnr2o5e9x-df8uusesyt9vnar6mck1v3jsj 172.17.***.***:2377 # 这一行是加入集群的命令
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
# 集群搭建好了,在主机上查看加入集群的命令
# 作为manager 主机 加入集群,在主机上输入命令
docker swarm join-token manager
会得到这个,把这个拿到另一台服务器上输入 docker swarm join --token SWMTKN-1-1rz3ji6sge1ohdfu0pxcvurheh1ynsteq9s6qwsyu80wnj9tqz-5baejzdodessul4npylyw5b9t 172.27.**.*:2377
# 作为worker 从机 加入集群,在主机上输入命令
docker swarm join-token worker # 步骤同上
# 查看集群情况,这条命令只能在manager机器上输入
docker node ls
[root@iZ7xva6bpev0nh2bbplvx6Z ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
bbg6lw6nsvgnd9bsqu0865ufl * iZ7xva6bpev0nh2bbplvx6Z Ready Active Leader 20.10.17
3n2fvd3vjp0hpp4yelz4fpdlg iZ7xva6bpev0nh2bbplvx7Z Ready Active 20.10.17
hwedxd44se9ypj4no5betn4kv iZ7xva6bpev0nh2bbplvx8Z Ready Active 20.10.17
qk8d9xwj0qu8h6kmardsy3c0m iZ7xva6bpev0nh2bbplvx9Z Ready Active Reachable 20.10.17
# Leader 表示是集群的第一台机器,肯定是manager机器了
# Ranchable 表示是其他的manager机器
# 空白的就是 worker 从机了
双主双从不符合Raft协议。这里学习使用为了省钱。流量也挺贵的;
Raft协议
docker集群采用的Raft协议:一致性协议
保证大多数节点可以存活。如果只有两个节点,则挂了一个,另外一个无法通过选举上位,因此需要保证节点至少有三个。
# 尝试
# 关掉一个manager
systemctl stop docker
# 然后去另一个manager上查看会发现
[root@iZ7xva6bpev0nh2bbplvx6Z ~]# docker node ls
Error response from daemon: rpc error: code = DeadlineExceeded desc = context deadline exceeded
# 无法显示集群信息了,崩了,因为两个manager,挂了一个,另一个无法通过Raft协议选举
systemctl start docker
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
bbg6lw6nsvgnd9bsqu0865ufl * iZ7xva6bpev0nh2bbplvx6Z Ready Active Reachable 20.10.17
3n2fvd3vjp0hpp4yelz4fpdlg iZ7xva6bpev0nh2bbplvx7Z Ready Active 20.10.17
hwedxd44se9ypj4no5betn4kv iZ7xva6bpev0nh2bbplvx8Z Ready Active 20.10.17
qk8d9xwj0qu8h6kmardsy3c0m iZ7xva6bpev0nh2bbplvx9Z Ready Active Leader 20.10.17
# docker重启后,自动加入集群,会发现,原来如果是Leader机器变成了Reachable机器了
# 不要在你关掉docker的manager机器上测试,他会找一会找不到,然后把你关掉的docker又启动回来了
# 从机worker 退出集群(从机退出不影响)
docker swarm leave
# 然后退出的这台机器已主机身份加入
# 再退出一台manager主机,就不会影响其他了,因为三台主机退出一个还剩两个,能进行选举
# 三主一从 good
[root@iZ7xva6bpev0nh2bbplvx7Z ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
bbg6lw6nsvgnd9bsqu0865ufl iZ7xva6bpev0nh2bbplvx6Z Unknown Active Unreachable 20.10.17
3n2fvd3vjp0hpp4yelz4fpdlg iZ7xva6bpev0nh2bbplvx7Z Down Active 20.10.17
xil6ct9l4i86qhq1qqeomnrl5 * iZ7xva6bpev0nh2bbplvx7Z Unknown Active Leader 20.10.17
hwedxd44se9ypj4no5betn4kv iZ7xva6bpev0nh2bbplvx8Z Unknown Active 20.10.17
qk8d9xwj0qu8h6kmardsy3c0m iZ7xva6bpev0nh2bbplvx9Z Unknown Active Reachable 20.10.17
部署应用
# 启动一个nginx服务
docker service create -p 8008:80 --name mynginx nginx
# 很多类似service的命令只能在manager机器上使用
# 查看service服务全部
docker service ls
[root@iZ7xva6bpev0nh2bbplvx6Z ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
3oit4v5r9wbd mynginx replicated 1/1 nginx:latest *:8008->80/tcp
只启动了一个服务
# 查看mynginx具体信息
docker service ps mynginx
[root@iZ7xva6bpev0nh2bbplvx6Z ~]# docker service ps mynginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
x3katk4qbk8g mynginx.1 nginx:latest iZ7xva6bpev0nh2bbplvx9Z Running Running 9 minutes ago
服务启动在这个机器上
# docker service 是集群命令,在每个manager机器上都能看到服务信息
# docker ps 是单机命令,只能在有启动服务的机器上才能看到服务信息
服务扩缩容
动态的将服务进行增加或减少
# 将我们的mynginx服务 创建10个
docker service update --replicas 10 mynginx
[root@iZ7xva6bpev0nh2bbplvx9Z ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
3oit4v5r9wbd mynginx replicated 10/10 nginx:latest *:8008->80/tcp
已启动了10个服务
# 查看发现均匀分布在集群的几个服务器上
docker ps
[root@iZ7xva6bpev0nh2bbplvx6Z ~]# docker service ps mynginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
x3katk4qbk8g mynginx.1 nginx:latest iZ7xva6bpev0nh2bbplvx9Z Running Running 17 minutes ago
twupl8i58obw mynginx.2 nginx:latest iZ7xva6bpev0nh2bbplvx6Z Running Running about a minute ago
k1jf7m1gbvph mynginx.3 nginx:latest iZ7xva6bpev0nh2bbplvx8Z Running Running about a minute ago
ybkedu9xqujl mynginx.4 nginx:latest iZ7xva6bpev0nh2bbplvx9Z Running Running 2 minutes ago
87ug7vpy1seb mynginx.5 nginx:latest iZ7xva6bpev0nh2bbplvx9Z Running Running 2 minutes ago
zxonfugqmdge mynginx.6 nginx:latest iZ7xva6bpev0nh2bbplvx7Z Running Running about a minute ago
vfjfrhstd52t mynginx.7 nginx:latest iZ7xva6bpev0nh2bbplvx7Z Running Running about a minute ago
87rlt010i0m4 mynginx.8 nginx:latest iZ7xva6bpev0nh2bbplvx8Z Running Running about a minute ago
gfmaeq6hqtoc mynginx.9 nginx:latest iZ7xva6bpev0nh2bbplvx6Z Running Running about a minute ago
m174oisn2wj5 mynginx.10 nginx:latest iZ7xva6bpev0nh2bbplvx7Z Running Running about a minute ago
docker service scale 命令和 docker service update 是一样的
# docker service update --replicas 1 mynginx
docker service scale mynginx=1
集群命令只能在manager机器上执行,无法再worker机器上执行
docker run # 单机命令
docker service create # 集群命令
docker ps # 单机命令
docker service ps # 集群命令
# 移除删除
docker service rm mynginx
Docker Stack
Docker 适用于开发和测试。Docker Stack 则适用于大规模场景和生产环境。
在 Compose 文件中定义应用,然后通过 docker stack deploy 命令完成部署和管理。