微服务的部署(Docker)
一 初识Docker
1.项目部署问题
- 大型项目组件较多,运行环境较为复杂,部署和维护困难
- 依赖关系复杂,容易出现兼容性问题
- 开发,测试,生产环境有差异
2.解决依赖的兼容问题
- 将应用的Libs(函数库),Deps(依赖),配置与应用一起打包
- 将每个应用放到一个单独的容器中去运行,避免相互干扰,且各个容器之间不可见。
3.解决不同操作系统
内核与硬件交互,提供操作硬件的指令。
系统应用封装内核指令函数,供使用人员调用。
Docker将用户程序所需要调用的系统函数库一同打包
Docker运行到不同操作系统时,直接基于打包的函数库,借助操作系统的Linux内核来运行。
Docker是一个快速交付应用,运行应用的技术。
1.Docker可将程序的依赖环境,运行环境一起打包为一个镜像,可以迁移到任何Linux系统
2.运行时利用沙箱机制形成隔离容器,各个应用互不干扰
3.启动,移除都可以通过命名完成
4.Docker和虚拟机
虚拟机是一种在一个操作系统中模拟另外一个操作系统,性能不如Docker。
Docker是操作系统的一个进程,体积小,性能好。
5.Docker的架构
1.镜像和容器
镜像(image): Docker将应用程序所需要的依赖,函数库,环境配置文件等打包在一起,称之为镜像。
容器(container):镜像中的应用运行之后的进程就是容器,只是Docker会给容器做隔离,对外不可见。
2.DockerHub
DockerHub是一个Docker镜像的托管平台,这样的平台成为Docker Registry。
DockerHub官方地址:Docker Hub Container Image Library | App Containerization
3.Docker架构
1.Docker是一个CS架构的程序,由两部分组成。
- 服务端(serve):Docker守护进程,负责处理Docker命令,镜像管理,容器等
- 客户端(client):通过命令或者RestAPI向Docker发送命令。可以在本地或远程向服务器发送指令。
二 Docker的使用
1.卸载Docker
1.Docker 分为 CE 和 EE 两大版本,其中 CE 为社区版,EE为企业版。
2.以下操作均基于 centos7 版本
安装之前先卸载,防止因为以前安装过导致失败。 ( \ 表示命令的换行)
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine \
docker-ce
提示 Another app is currently holding the yum lock; waiting for it to exit… 时,运行以下命令,然后重新执行 yum 命令即可
rm -f /var/run/yum.pid
卸载完成,即可以重新安装 Docker
2.安装Docker
1.安装yum工具
第一步先要虚拟机联网,然后安装 yum工具
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2 --skip-broken
2.更新镜像源
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce./g'
/etc/yum.repos.d/docker-ce.repo
yum makecache fast
3.安装Docker
docker-ce为社区免费版。(-y 表示安装过程中允许所有)
yum install -y docker-ce
4.启动Docker
练习过程中可以关闭防火墙,以方便使用。实际应用中则需要逐一去配置。
针对防火墙的完整操作: 操作Linux系统以及Java环境搭建
# 2.暂时关闭防火墙
systemctl stop firewalld
# 3.永久关闭防火墙
systemctl disable firewalld
启动 Docker
# 运行docker
systemctl start docker
# 开机启动 docker
systemctl enable docker
# 重启docker
systemctl restart docker
# 检查docker 状态
systemctl status docker
# 检查 docker 版本
docker -v
# 关闭docker
systemctl stop docker
5.配置镜像地址
推荐阿里云镜像,配置镜像加速器的地址:容器镜像服务 (aliyun.com)
配置方法如下,配置成功后,后面下载 docker 镜像,将都从阿里云的镜像地址下载
# 创建 文件路径
sudo mkdir -p /etc/docker
# 写入阿里云的镜像地址
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://mw0lfy5i.mirror.aliyuncs.com"]
}
EOF
# 重新加载 daemon 文件
sudo systemctl daemon-reload
# 重启 docker
sudo systemctl restart docker
三 Docker的操作
1.镜像命令组成
镜像命令一般由两部分组成,即 Repository : Tag
前部分是指镜像的名称,后部分是指镜像的版本,前后通过冒号( : ) 连接。
未指定版本时,默认下载最新版本,即 latest。
2.镜像操作命令
1.镜像操作示意图
2.镜像操作命令
# 查看 docker 命令及帮助
docker --help
# 查看指定命令的帮助
docker [command] --help
# 查看当前所拥有的镜像
docker images
1 拉取镜像
# 拉取镜像,未指定版本则拉取最新版,latest
docker pull [ image : {version} ]
# 示例:拉取 nginx1.22版
docker pull nginx:1.22
2 导出镜像
# 导出一个镜像到磁盘的指定文件,同一个镜像有多个版本时,需要指定版本号
docker save -o [file] [image]:[tag]
# 示例:将 nginx 镜像 导出到 /image/mynginx.tar 文件中
docker save -o /image/mynginx.tar nginx
3 删除镜像
# 删除一个镜像,(删除镜像时必须指定版本号)
docker rmi [image]:[tag]
# 示例:删除 nginx 1.22
docker rmi nginx:1.22
4 加载镜像
# 将程序的镜像文件加载到 docker 中, ( -q 表示是否输出加载的过程)
docker load -i [ file ] { -q }
# 示例:将 nginx镜像 文件加载到 docker中
docker load -i /image/mynginx.tar
5 推送镜像
# 将镜像文件推送到远程
docker push -a [name]:[tag]
3.容器操作命令
1.容器操作示意图
1.使用 docker stop 停止容器后,容器的进程将会被杀死,无法通过 docker unpause 重启。只能通过 docker start 重启。
2.容器操作命令
1.创建并运行一个容器
创建并运行容器的命令较为复杂且不尽相同,具体可参考提供镜像的官方文档。
# 创建并且运行一个容器
docker run --name [container] -p [serverPort]:[containerPort] -d [image]
# 示例:创建一个 nginx 的容器
docker run --name myNginx -p 8080:80 -d nginx
- docker run : 运行并创建一个容器
- –name : 为容器命名,需唯一
- -p :端口映射,将宿主机的端口映射到容器的端口。左侧是宿主机端口,右侧是容器端口。将原本隔离的容器对外暴露端口,便于用户访问
- -d :后台运行
- image:需要运行的镜像名称
2.查看容器信息
# 查看容器
docker ps
# 查看全部容器
docker ps -a
其他命令通过 docker ps --help 自查
3.删除容器
# 删除一个容器
docker rm [container]
# 强制删除一个运行中的容器
docker rm [container] -f
# 一键删除全部容器,包含运行中的
docker rm $(docker ps -aq) -f
# 示例
docker rm myNginx
4.容器状态的转换
# 暂停容器
docker pause [container]
# 重启容器
docker unpause [container]
# 停止容器
docker stop [container]
# 重新运行容器
docker start [container]
# 重新运行全部容器
docker restart $(docker ps -a -q)
5.查看容器日志
# 查看指定日期的运行日志
docker logs [container]
# 持续跟踪日志(霸屏模式)
docker logs [container] -f
# 示例:查看 myNginx 容器的日志
docker logs myNginx
6.进入容器执行命令
# 进入容器内部执行一条命令
docker exec -it [container] bash
-
docker exec:进入容器内部执行一个命令
-
-it : 给当前进入的容器创建一个标准输入,输出终端,便于与容器交互
-
bash : 进入容器执行的命令,bash 是一个linux 终端交互命令
替换命令:sed -i
4.数据卷操作命令
1.容器与数据耦合的问题
-
不便于修改:进入容器内部修改很不方便
-
数据不可复用 :所修改的内容在新的容器上不可复用
-
升级维护困难:数据在容器内,如果升级容器,必然删除旧容器导致数据一起被删除
2.数据卷
数据卷是一个虚拟目录,指向宿主机文件系统中的某一个目录
数据卷中的目录指向宿主机的 /var/lib/docker/volumes 路径下的同名文件夹。
容器在创建以后,可以直接使用这个数据卷。
让容器的内部目录与数据卷相关联,此时它的本质是跟宿主机的指定目录相关联。
当修改宿主机目录下的内容,会立即反应到容器内部的关联目录下,反之亦然。
简单来说,就是宿主机文件系统和容器通过数据卷搭建起了沟通的桥梁。
创建数据卷后,数据卷可被多个容器共享,且删除容器并不会影响到数据卷。
3.数据卷基本语法
1.创建数据卷
# 创建一个数据卷
docker volume create [volume]
2.查看已创建的数据卷
# 查看创建的数据卷
docker volume ls
# 查看指定数据卷所在的位置(其中的Mountpoint是物理磁盘的位置)
docker inspect [volume]
docker volume inspect [volume]
3.删除数据卷
# 删除未使用的数据卷
docker volume prune
# 删除指定数据卷
docker volume rm [volume]
4.挂载数据卷
创建容器时,可以通过 -v 参数来挂载一个数据卷。
-v 参数示例:-v html:/root/html
将一个名为 html 的数据卷挂载到容器内的 /root/html 的位置上
以下是Nginx的完整示例
# 1.创建一个名为 html 的数据卷
docker volume create html
# 2.创建 Nginx 镜像容器,并且挂载数据卷,指定端口映射,(注意:数据卷不存在时将会自动创建)
docker run --name myNginx -p 8080:80 -v html:/usr/share/nginx/html -d nginx:1.22
5.挂载目录
可以通过指定命令,将宿主机的目录或文件直接挂载到 Docker 容器内
- -v [宿主机目录]:[容器内部目录]
- -v [宿主机文件]:[容器内部文件]
# 挂载宿主机的mysql数据库文件目录和mysql配置文件到容器中的对应位置
# 对应位置在 DockerHub 上查询
docker run \
--name mysql5.7 \
-p 3307:3306 \
-v /temp/mysql/my.conf:/etc/mysql/my.cnf \
-v /temp/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:5.7
一般情况下,不推荐直接替换MySQL的配置文件,而是采用合并的方式,按照镜像内的 mysql 配置文件中提供的地址进行挂载,具体可在DockerHub查询
# 将存放我们自己配置文件的文件夹路径,挂载到容器内的 /etc/mysql/mysql.conf.d 或者 /etc/mysql/conf.d
docker run \
--name mysql5.7 \
-p 3307:3306 \
-v /temp/mysql/:/etc/mysql/mysql.conf.d \
-v /temp/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:5.7
6.挂载方式对比
1.数据卷挂载耦合度低,由 Docker 来管理,但目录较深,不好找。
2.目录挂载耦合度较高,由我们自己去管理。
四 自定义镜像
1.镜像结构
镜像是将应用程序及其需要的系统函数库,环境,配置,依赖等统一打包。
镜像是一个分层结构,每一层称之为一个Layer
- BaseImage:基础镜像层,包含基本的系统函数库,环境变量,文件系统等。
- Entrypoint: 入口,是镜像中启动应用的命令
- 其他:在BaseImage的基础上添加依赖,安装程序,完成整个应用的安装和配置。
2.DockerFile
Dokcerfile是一个文本文件,里面包括一个个的指令,用指令来说明要执行什么操作。每一个指令都会形成一个Layer。
Dockerfile第一行必须是 FROM
3.构建 JAVA项目
1.准备指定版本的JDK(此处使用JDK8)和一个java项目的jar包,将其放在同一个目录下。
2.在目录下创建名为 “ Dockerfile ” 的文件,复制一下内容。(注意区别版本号)
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK安装位置
ENV JAVA_DIR=/usr/local
# 复制jdk和jar包
COPY ./demo.jar /temp/app.jar
COPY ./jdk8.tar.gz /$JAVA_DIR
# 安装JDK(jdk1.8.0_341为解压后的目录名称)
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_341 ./java8
#配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 暴露端口
EXPOSE 8080
ENTRYPOINT java -jar /temp/app.jar
3.准备完成,一同复制到服务器或虚拟机
4.运行构建命令
docker build -t demo:tag [Dockerfile Path]
# 示例:
docker build -t people_manager:1.0 .
5.构建完成后可通过 docker images 命令查看,并且运行
docker run --name people_manager -p 8080:8080 -d people_manager:1.0
4.基于Openjdk:8构建项目
对于每次构建Java项目都需要的内容,openjdk8已经全部集成进去并且构建成了镜像,我们基于Openjdk:8构建,则不再需要那么复杂。
FROM openjdk:8-jdk-alpine
COPY demo.jar demo.jar
EXPOSE 8080
ENTRYPOINT java -jar dockerdemo.jar
五 DockerCompose
1.认识DockerCompose
DockerCompose可以基于Compose文件快速的部署分布式应用,而无需手动去创建容器
Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行,内容格式使用yaml格式
DockerCompose下载地址:Releases · docker/compose · GitHub
# 1.安装DockerCompose(安装其他版本,请修改v2.2.2)
sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 2.或者可以使用高速下载通道
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# 3.下载完成的文件在 /usr/local/bin 目录下
cd /usr/local/bin
# 4.修改文件权限,用于执行二进制文件
sudo chmod +x /usr/local/bin/docker-compose
2.部署微服务集群
使用 docker-compose 进行微服务的集群部署
# 版本号
version: "3.2"
# 服务列表
services:
# 服务名: nacos 服务
nacos:
# 镜像及版本号
image: nacos/nacos-server
# 环境参数,具体用法参考对应镜像的文档
environment:
MODE: standalone
# 对外映射的端口
ports:
- "8848:8848"
redis:
image: redis
ports:
- "6379:6379"
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- "$PWD/mysql/data:/var/lib/mysql"
- "$PWD/mysql/conf/:/etc/mysql/mysql.conf.d"
ports:
- "3306:3306"
alibaba-order:
# 需要构建的镜像及Dockerfile文件目录
build: ./alibaba-order
alibaba-user:
build: ./alibaba-user
gateway:
build: ./gateway
# 通过统一网关对外映射唯一端口,其他微服务不映射端口
ports:
- "8080:8080"
其他更多用法,参考 docker-compose 文档 Overview | Docker Documentation
推荐一个中文文档地址:Docker中文文档 Docker概述-DockerInfo
构建镜像时的准备文件如下
此时的Dockerfile文件内容如下
FROM openjdk:8-jdk-alpine
COPY ./app.jar ./temp/app.jar
ENTRYPOINT java -jar ./temp/app.jar
完成之后,将全部文件上传至服务器。
注意:项目打包时需要将各个微服务的相关地址更改为 docker-compose 部署时所使用的微服务名,否则无法被访问。
# 示例
http://localhost:8848 --> http://nacos:8848
jdbc:mysql://localhost:3306/cloud_order --> jdbc:mysql://mysql:3306/cloud_order
docker-compose 内部做了配置,各个微服务之间可以通过服务名称直接调用。
最后,切换至 docker-compose 文件目录下,运行即可
# 运行 docker-compose( -d 表示后台运行)
docker-compose up -d
# 更多命令通过帮助获取
docker-compose --help
踩坑点:nacos 服务相比其他微服务启动较慢,如果需要向nacos注册的微服务启动失败,可以通过重启解决。
六 Docker镜像仓库
1.搭建私有镜像仓库
镜像仓库(Docker Registry)分为公有和私有仓库
- 公有仓库:类似 DockerHub,提供一些公共镜像
- 私有仓库:企业中基于微服务开发的镜像,一般情况下需要放在私有仓库
私有仓库的搭建基于Docker提供的一个镜像 ( registry )来实现
1.简化版私有仓库
具备完整功能,但是没有图形化界面,搭建方式简单,默认端口为5000
docker run -d \
--name registry \
-p 5000:5000
-v registry:/var/lib/registry
registry
2.图形界面版本
非docker 官方提供,由个人在 registry 基础上开发而成。通过 docker-compose 来部署
version: '3.0'
services:
registry:
image: registry
volumes:
- ./registry/data:/var/lib/registry
ui:
image: joxit/docker-registry-ui:static
ports:
- "5000:80"
environment:
- REGISTRY_TITLE=Shawn'registry
# 此处使用的是 registry 服务名
- REGISTRY_URL=HTTP://registry:5000
depends_on:
# 依赖的镜像
- registry
3.配置Docker信任地址
#1.打开要修改的文件
vim /etc/docker/daemon.json
#2.添加需要信任的服务器地址(以下地址是编写此文档时的虚拟机地址)
"insecure-registries":["http://192.168.169.133:5000"]
#3.重新加载
systemctl daemon-reload
#4.重启 docker
systemctl restart docker
2.向镜像仓库推送镜像
推送镜像到私有服务器必须先tag
1.重新 tag 本地镜像,名称前缀为私有仓库地址
通过 tag,可以将一个镜像重命名为另一个镜像
# 将一个镜像 tag 为另一个镜像,前缀的服务器地址为私有云地址
docker tag [image]:[tag] 192.168.169.133:5000/[image]:[tag]
# 示例:
docker tag test:1.1 192.168.169.133:5000/test:1.1
# 推送:
docker push 192.168.169.133:5000/test:1.1
推送完成后,便可以在私有云的WebUI中看到。
3.从镜像仓库拉去镜像
docker pull 192.168.169.133:5000/test:1.1
完结撒花。