Docker进阶
笔记来自
狂神视频
Dockerfile
swarm教程
前言
- 看完docker的入门笔记后会发现虽然安装东西很容易
- 但是启动,网络通信,端口映射,文件挂载还是麻烦得不行
- 入门的操作都很麻烦,到了进阶和高级会现在这些东西都是一键完成
- 能用配置文件解决的,绝对不打命令,因为配置文件可以保存,容易看得多
Docker Compose 安装
- 当需要多次重复一样的docker操作时
- 可以使用该技术,写好yml配置文件,然后用命令执行即可
- 这个是启动在一个机器上的配置文件
- 下载安装依赖
# 设置源
curl -L https://github.com/docker/compose/releases/download/1.8.0/run.sh > /usr/local/bin/docker-compose
# 授权并安装,需要等到几个 pull complete完成才行
chmod +x /usr/local/bin/docker-compose
# 查看版本
docker-compose --version
Compose 使用
- 单机服务
- 编写配置文件,执行运行命令就行
- 配置文件操作的都是dockor文件
- 配置文件教程,具体看官网
- 启动命令
# -d 是后台运行
docker-compose up -d
- 可以配合dockerfile使用,但是更建议先把dockerfile打包成镜像上传到镜像服务器,为什么,往下看【实操发布】有解释
- 实例一:搭建一个wordpress博客,查看【无分类/搭个博客】笔记
- 实例二:搭建一个微服务,狂神视频第7集,首先需要打包一个jar文件,然后把jar用dockorfile制作成dockor文件,然后写一份compose配置文件,然后把三个文件都丢到服务器上,运行命令就行
Swarm
- 服务器集群技术
- 集群技术练习需要租用云服务器,查看【租用服务器】笔记
- 集群有两个身份
- 一个叫管理者manager,需要有多个,至少三个
- 一个叫工作中worker,无数个
- 安装好dockor后
docker swarm --help
有反应就说明安装成功
# init操作
# 随便找一个服务器输入
# IP的获取方式是 ip addr
docker swarm init --advertise-addr 【内网IP地址】
# 查看集群的节点
docker node ls
# 在init身份或者manager身份的服务器上输入
docker swarm join-token worker
docker swarm join-token manager
# 其中一条就会生成一个token命令,把这个命令在另外安装有docker的服务器上执行就会加入到集群里
# 新加入的机器不享有原集群里的服务,需要删除服务,再添加才能共享
# worker离开集群
docker swarm leave
# manager离开集群
docker swarm leave --force
- 创建服务
- 服务创建后,哪怕只有一个也是所有的都可以访问
- 但是如果正好运行了这个服务的那台机器死机了,所有的都不能访问
- 所以应该多开几台
# --replicas 1 这个不写也是默认的
# 一点要加版本,就算是latest也一定要写上去
docker service create --replicas 1 --name web01 -p 88:80 nginx:latest
# 这个命令会在当前机器下载安装镜像,使用 docker image ls 可以看到
# 如果当前机器上有这个镜像,就不用下载直接启动
# 跟docker run 一样这个服务也是可以在ps里查看到并且进入进行修改的
# 查看ps服务
docker ps
# 进入服务
docker exec -it 【id】 /bin/bash
# 找到集群机器安装了上面服务器的机器后
# 查看详情
docker service inspect web01
# 查看本机器上运行的服务
docker service ls
# 查看某个服务运行在哪些机器上
docker service ps 【nginx】
# 扩容缩容
# 这样集群的机器又会
docker service scale web01=3
# 删除service
docker service rm 服务名
# docker或者docker swarm都是有一个默认网络的
# 只有在相同网络里才可以通信
# 创建网络
# docker network create -d [overlay|bridge] [自定义名称]
docker network create --driver overlay my_network
# 还有一种写法是写在yml里,运行yml时就会自动创建
# 查看网络
docker network ls
- 运行自定义的镜像
# 找个文件夹放入 jar包和dockerfile
FROM java:8
ADD eureka-7001-1.0-SNAPSHOT.jar eureka.jar
EXPOSE 7001
ENTRYPOINT ["java","-jar","eureka.jar"]
# 打包命令
docker build -t eureka:v1 .
# swarm 集群运行的命令
docker service create --replicas 1 --name eureka -p 7001:7001 eureka:v1
Secret
- 就是集群版的compose,通用也是用yml配置,如何配置查看官方文档
- 可以配合dockerfile使用,但是更建议先把dockerfile打包成镜像上传到镜像服务器,为什么,往下看【实操发布】有解释
- 两个可视化工具,Portainer 和 visualizer,结合secret写个配置
version: "3"
services:
visualizer:
image: dockersamples/visualizer
ports:
- "9001:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
portainer:
image: portainer/portainer
ports:
- "9000:9000"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
- volumes是映射文件的配置,这些路径和文件一定要自己手动创建,如果是配置文件一定要配置正确
docker stack deploy --compose-file=docker-compose.yml 【name】
# 如果启动后 docker image ls没看到镜像说明下载太慢,应该修改镜像加速服务
# 如果启动后有镜像但是 docker service ls 是 0/n,说明没启动成功
# 没启动成功可以用 docker service ps 【name】 查看error原因
使用Compose和Secret发布项目注意
- dockerfile使用需要先往机器上传文件,很麻烦,建议先在一个机器上生成镜像,上传镜像服务器,然后yml配置文件都配置成下载地址,方便
- 不管是Secret或者Compose都有挂载文件的配置,挂载文件是需要自己提前创建好的,不会自动生成
- Secret是个集群服务,在这个上面启动的服务仅限可以无限启动的服务,而且不需要不同的配置文件的服务,比如jar包,爬虫服务
- 但是jar包也是会产生日志文件什么的,需要使用挂载功能,所以需要全部提前创建好,如果觉得麻烦可以直接挂载在服务器已有的文件夹下,就不需要自己一个个创建了
- Secret不适用的服务都是用Compose启动,比如nginx,nginx的html文件夹和配置文件是需要不同的,比如数据库,数据库在Secret上启动几百个也是没用的,因为没有数据
- 服务如果有启动顺序,需要配置好或者按顺序一个个执行
实操发布springcloud项目
- 失败了两天之后我终于成功了,坑是真的多
- 先到服务器安装mysql和redis
version: '2'
services:
mysql:
restart: always
image: mysql:8
ports:
- "3306:3306"
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--default-time-zone=+8:00
environment:
MYSQL_ROOT_PASSWORD: "password" #root登陆密码
volumes:
- "/docker/mysql/db:/var/lib/mysql"
- "/docker/mysql/conf/my.cnf:/etc/my.cnf"
redis:
restart: always
image: redis
environment:
- TZ=Asia/Shanghai
command: redis-server /usr/local/etc/redis/redis.conf
ports:
- "6379:6379"
volumes:
- /docker/redis/data:/data
- /docker/redis/redis.conf:/usr/local/etc/redis/redis.conf
# my.cnf
# [mysqld]
# user=mysql
# default-storage-engine=INNODB
# character-set-server=utf8mb4
# [client]
# default-character-set=utf8mb4
# [mysql]
# default-character-set=utf8mb4
# redis.conf
# requirepass redispassword # 指定密码
# appendonly yes # 本地持久化
- 这次的操作只启动eureka和order
- 启动很容易,但是order一直连接不上eureka等等问题
- 先把代码的配置改成服务的域名
# 这是eureka的
server:
port: 7001
eureka:
instance:
hostname: a.pdt1997.top
client:
fetch-registry: false # 不用检索服务 自己是注册中心
register-with-eureka: false #不向注册中心注册自己
service-url:
defaultZone: http://a.pdt1997.top:7001/eureka
# 这是order的,省略redis和mysql等连接配置
spring:
application:
name: order
eureka: #设置eureka注册服务的地址
client:
service-url:
defaultZone: http://a.pdt1997.top:7001/eureka/
instance:
instance-id: order-9001 #配置服务的别名
prefer-ip-address: true # 注册的时候使用ip注册
- 写两个dockerfile
FROM java:8
# 这里要根据打包文件去改名字
ADD eureka-7001-1.0-SNAPSHOT.jar eureka.jar
EXPOSE 7001
ENTRYPOINT ["java","-jar","eureka.jar"]
- 把eureka和order打包成jar包和两个dockerfile一起丢到某一个服务器上
- 目录如下
- /docker/springcloud-pdt
- eureka
- xxx.jar
- dockerfile
- order
- xxx.jar
- dockerfile
- 这里要放一个 docker-compose.yml ,往下看
- 把jar包打包成镜像,并且上传到阿里的dockerhub
- 为什么不直接使用镜像启动,因为这个镜像只存在于当前服务器,而swarm扩容时别的机器是没有镜像的,就会报错:no such image,所以要像上面的nginx一样,上传,再下载下来
- 去阿里控制台搜索 容器镜像服务 就能使用镜像了
- 仓库创建操作如下
- 下一步后选择本地仓库就行
- 注意:第二天打开的时候会发现镜像怎么都不见了,因为在Logo旁边有个地区选择,打开地区不一样,镜像不一样,建议全部上传到同一个地区
- 创建成功点击管理,里面所有的操作命令都写好了,复制直接使用
# 打包操作,打包后可以用 docker image ls查看
docker build -t eureka:v1 .
# 登陆,输入密码,连接成功就行,只需要登录一次
docker login --username=15013961618 registry.cn-hangzhou.aliyuncs.com
# 两步完成上传,ImageId上刚才打包出来的镜像的id
docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/pdt/eureka:[镜像版本号]
docker push registry.cn-hangzhou.aliyuncs.com/pdt/eureka:[镜像版本号]
- 上传镜像成功后,去阿里刷新下页面看看是不是真的有,然后可以把本地的镜像删了,模拟新服务器启动的全新操作
- 打包上传镜像是可以在idea实现的,就不需要上面这么麻烦的操作了,但是我不会
# 本地打包一份,上传时又打包一份,所以查看镜像的时候会发现两个一样的id,两个不一样的名字
docker image ls
# REPOSITORY TAG IMAGE ID
# order v1 8968ce1119f2
# registry.cn-hangzhou.aliyuncs.com/pdt/order v1 8968ce1119f2
# 删除
docker rmi -f 8968ce1119f2
- 删除完再检查下机器是不是足够干净
docker ps -a
docker image ls
docker service ls
- 配置网络,在docker里所有的容器都是不相连的
# 创建网络
docker network create --driver overlay my_network
- 写一个 docker-compose.yml 文件
version: '3'
services:
eureka:
restart: always
image: registry.cn-hangzhou.aliyuncs.com/pdt/eureka:v2 # 镜像名:标签名
hostname: a.pdt1997.top # 注册中心的hostname一定要有,且必须和代码中配置文件里的hostname一致
networks:
- my_network # 加入的网络
environment:
- TZ=Asia/Shanghai
ports:
- "7001:7001" # 映射的端口号,和代码中配置文件里的端口号一致
order:
restart: always
image: registry.cn-hangzhou.aliyuncs.com/pdt/order:v2
depends_on:
- eureka
ports:
- "9001:9001"
links:
- eureka
networks:
- my_network # 加入的网络
#指定网络
networks:
my_network:
##使用已有的网路
external:
name: my_network
- 把配置文件上传到上面的备注位置上,进入这个位置,执行启动命令
docker stack deploy --compose-file=docker-compose.yml springcloud-pdt
# 他打印出下面两句话后就结束了
# Creating service springcloud-pdt_eureka
# Creating service springcloud-pdt_order
# 查看服务
docker service ls
# 如果服务是 0/1,就再等等,等到 1/1 启动完成
- 记得需要打开防火墙端口 和 安全组端口
- 访问可以看到,erueka启动成功,order启动成功,并且order连接上eureka了,需要等几分钟才会启动成功,连接上去,要有耐心
- 扩容
# 扩容前在每个机器上执行
docker image ls
docker ps
# 查看上面的服务是下载安装启动在哪个机器上
# 扩容
docker service scale springcloud-pdt_order=2
# 扩容完成后,在每台机器上执行
docker service ls
docker image ls
docker ps
# 只要看到有一台原本没有image和ps的机器被扩容成功,就发布成功了
- 测试mysql和redis
# 可以打开日志,然后调用接口,看看有没有打印日志
docker service logs -f --tail=50 服务名称
# 可以工具连接redis和mysql查看有没有存入数据什么的
- 第一次调用接口打印sql日志,第二次取redis缓存,完美
镜像已经上传阿里镜像仓库,代码和docker-yml文件已经上传到github