项目部署问题

image-20230816195554477

image-20230816195719226

image-20230816200146684

Docker如何解决大型项目依赖关系复杂,不同组件依赖的兼容性问题?

  • Docker允许开发中将应用、依赖、函数库、配置一起打包形成可移植镜像

  • Docker应用运行在容器中,使用沙箱机制,相互隔离

Docker如何解决开发、测试、生产环境有差异的问题?

  • Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可以在任意Linux操作系统上运行

一、Docker架构

1.1 基本概念

镜像:Docker将应用程序及其所需要的依赖、函数库、环境、配置等文件打包在一起,称为镜像。

容器:镜像中的应用程序运行后形成的进程就是容器,只是Docker会给容器做隔离 ,对外不可见。

image-20230816211237418

DockerHub:DockerHub是一个DockerHub镜像托管平台。这样的平台称为Docker Registry。

1.2 架构

Docker是一个CS架构,由两部分组成:

服务端(server):Docker守护进程,负责处理Docker命令,管理镜像、容器等。

客户端(client):通过命令或RestAPI向Docker服务端发送命令。可以在本地或远程向服务器发送指令。

二、CenOs安装Docker

2.1 安装Docker

Docker 分为 CE 和 EE 两大版本。CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月。

Docker CE 分为 stable testnightly 三个更新频道。

官方网站上有各种环境下的 安装指南,这里主要介绍 Docker CE 在 CentOS上的安装。

2.2 CentOS安装Docker

Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10, CentOS 7 满足最低内核的要求,所以我们在CentOS 7安装Docker。

2.2.1 卸载(可选)

如果之前安装过旧版本的Docker,可以使用下面命令卸载:

1
2
3
4
5
6
7
8
9
10
11
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

2.2.2 安装docker

首先需要大家虚拟机联网,安装yum工具

1
2
3
yum install -y yum-utils \
device-mapper-persistent-data \
lvm2 --skip-broken

然后更新本地镜像源:

1
2
3
4
5
6
7
8
# 设置docker镜像源
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

然后输入命令:

1
yum install -y docker-ce

docker-ce为社区免费版本。稍等片刻,docker即可安装成功。

2.2.3 启动docker

Docker应用需要用到各种端口,逐一去修改防火墙设置。非常麻烦,因此建议大家直接关闭防火墙!

启动docker前,一定要关闭防火墙后!!

1
2
3
4
# 关闭
systemctl stop firewalld
# 禁止开机启动防火墙
systemctl disable firewalld

通过命令启动docker:

1
2
3
4
5
systemctl start docker  # 启动docker服务

systemctl stop docker # 停止docker服务

systemctl restart docker # 重启docker服务

然后输入命令,可以查看docker版本:

1
docker -v

如图:

image-20210418154704436

2.2.4 配置镜像加速

docker官方镜像仓库网速较差,我们需要设置国内镜像服务:

参考阿里云的镜像加速文档:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

2.3 CentOS7安装DockerCompose

2.3.1 下载

Linux下需要通过命令下载:

1
2
# 安装
curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

如果下载速度较慢,或者下载失败,可以使用课前资料提供的docker-compose文件:

image-20210417133020614

上传到/usr/local/bin/目录也可以。

2.3.2 修改文件权限

修改文件权限:

1
2
# 修改权限
chmod +x /usr/local/bin/docker-compose

2.3.3 Base自动补全命令:

1
2
# 补全命令
curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

如果这里出现错误,需要修改自己的hosts文件:

1
echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts

2.3.4 Docker镜像仓库

搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。

官网地址:https://hub.docker.com/_/registry

2.3.5 简化版镜像仓库

Docker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,但是没有图形化界面。

搭建方式比较简单,命令如下:

1
2
3
4
5
6
docker run -d \
--restart=always \
--name registry \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry

命令中挂载了一个数据卷registry-data到容器内的/var/lib/registry 目录,这是私有镜像库存放数据的目录。

访问http://YourIp:5000/v2/_catalog 可以查看当前私有镜像服务中包含的镜像

2.3.6 配置Docker信任地址

我们的私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:

1
2
3
4
5
6
7
8
# 打开要修改的文件
vi /etc/docker/daemon.json
# 添加内容:
"insecure-registries":["http://192.168.150.101:8080"]
# 重加载
systemctl daemon-reload
# 重启docker
systemctl restart docker

2.3.7 带有图形化界面版本

使用DockerCompose部署带有图象界面的DockerRegistry,命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3.0'
services:
registry:
image: registry
volumes:
- ./registry-data:/var/lib/registry
ui:
image: joxit/docker-registry-ui:static
ports:
- 8080:80
environment:
- REGISTRY_TITLE=传智教育私有仓库
- REGISTRY_URL=http://registry:5000
depends_on:
- registry
1
docker-compose up -d

推送镜像到私有镜像服务必须先tag,步骤如下:

  1. 重新tag本地镜像,名称前缀为私有仓库的地址:192.168.150.101:8080
1
docker tag nginx:latest 192.168.150.101:8080/nginx:1.0
  1. 推送镜像
1
docker push 192.168.150.101:8080/nginx1.0
  1. 拉取镜像
1
docker pull 192.168.150.101:8080/nginx:1.0

三、Docker基本操作

3.1 镜像命令

镜像名称一般有两部分组成:[repository]:[tag]

如果没有指定tag,默认是latest,代表最新版本的镜像

image-20230817123410158

image-20230817123846249

案例

从DockerHub中拉取一个nginx镜像并查看。

1
2
3
4
# 拉取一个nginx镜像
docker pull nginx
# 查看镜像
docker images

利用docker save命令将nginx镜像到处到磁盘,然后通过load加载回来

1
2
3
4
5
6
7
8
9
10
11
12
# 打包镜像为压缩包
docker save -o nginx.tar nginx:latest
# 查看文件
ls -l
# 删除nginx镜像
docker rmi nginx:latest
# 查看是否删除
docker images
# 加载压缩包恢复成镜像
docker load -i nginx.tar
# 查看镜像
docker images

3.2 容器命令

image-20230817131037099

案例1

创建并运行一个nginx容器。

1
docker run --name mynginx -p 80:80 -d nginx
  • docker run:创建并运行一个容器

  • –name:给容器起一个名称

  • -p:将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口。

    image-20230817135002202

  • -d:后台运行

  • -e KEY=VALUE:设置环境变量

  • nginx镜像名称

    • 一般分为两部分,镜像名和版本号[repository]:[tag],不写tag默认是最新版本
    • 例如:mysql:5.7
1
2
3
4
5
# 查看容器
docker ps
# 查看日志,加上-f是持续跟踪日志
docker logs mynginx
docker logs -f mynginx

案例2

进入nginx容器,修改html文件的内容。

  1. 进入容器。
1
docker exec -it mynginx bash
  • docker exec: 进入容器执行一个命令。
  • -it:给当前进入的容器创建 一个标准的输入、输出终端,允许我们与容器交互。
  • mynginx:要进入容器的名称。
  • bash:进入容器后执行的命令,bash是一个linux终端交互命令。
1
2
3
4
5
cd /usr/share/nginx/html
#修改内容
sed -i 's#Welcome to nginx#huanyingni#g' index.html
# 退出容器
exit
  1. 关闭容器,启动容器,删除容器
1
2
3
4
5
6
7
8
# 关闭容器
docker stop mynginx
# 显示所有容器,默认只显示运行中的容器,-a也展示挂掉的容器
docker ps -a
# 启动容器
docker start mynginx
# 删除容器
docker rm -f mynginx

3.3 数据卷命令

容器和数据耦合问题

image-20230817144627733

数据卷是一个虚拟目录,指向宿主机文件系统中的某个目录。

image-20230817150104709

数据卷的操作基本语法如下:

1
docker volume [COMMAND]

docker volume 命令是数据卷操作,根据命令后面跟随的Command来确定下一步操作:

命令 描述
create 创建一个volume
inspect 显示一个或多个volume的信息
ls 列出所有volume
prune 删除未使用的volume
rm 删除指定的volume
1
2
3
4
5
6
7
8
9
10
# 创建一个数据卷
docker volume create html
# 显示数据卷的信息
docker volume inspect html
# 列出所有数据卷
docker volume ls
# 删除未使用的volume
docker volume prune
# 删除指定数据卷
docker volume rm html

3.3.1 数据卷挂载

我们在创建容器时,可以通过-v参数来挂载一个数据卷到某一个容器目录。

容器创建时,如果发现挂载的数据卷不存在时,会自动创建。

image-20230817151921635

创建一个nginx容器,修改容器内的html目录内的index.html内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 创建容器并挂载到html数据卷
docker run --name mynginx -p 80:80 -v html:/usr/share/nginx/html -d nginx
# 查看数据卷的信息,找出对应的宿主机目录
docker volume inspect html
[
{
"CreatedAt": "2023-08-17T00:23:29-07:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]
# 进入目录修改信息:wq!保存退出
cd /var/lib/docker/volumes/html/_data
vim index.html

挂载数据卷时,如果数据卷不存在会自动创建。

3.3.2 目录挂载

目录的挂载必须以/或者./开头,不然会被识别为数据卷。

image-20230817154553269

创建并运行一个mysql容器,将宿主机目录直接挂载到容器。

  1. 在将课前资料中的mysql.tar文件上传到虚拟机,通过load命令加载为镜像
  2. 创建目录/tmp/myql/data
  3. 创建目录/tmp/myql/conf,将课前资料提供的hmy.cnf文件上传到/tmp/myql/conf
  4. 去DockerHub查阅资料,创建并运行MySQL容器,要求:
    • 挂载/tmp/myql/data到mysql容器内数据存储目录
    • 挂载/tmp/myql/conf/hmy.cnf到mysql容器的配置文件
  5. 设置MySQL密码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 创建目录
mkdir -p /tmp/mysql/data
mkdir -p /tmp/mysql/conf
# 通过Xftp将文件上传到/tmp目录下
cd /tmp
# 将压缩包还原成镜像
docker load -i mysql.tar
# 创建容器并挂载
docker run \
--name Mysql \
-e MYSQL_ROOT_PASSWORD=root \
-p 3306:3306 \
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
-v /tmp/mysql/data:/var/lib/mysql \
-d mysql:5.7.25

3.4 查看容器挂载的目录

1
2
3
docker inspect containerid | grep -A 10 "Mounts"
# 需要python环境
docker inspect containerid -f '{{json.Mounts}}' | python -m json.tool

四、Dockerfile自定义镜像

镜像结构

镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成

image-20230817165349864

镜像是分层结构,每一层称为一个Layer

  • Baselmage层:包含级别的系统函数库、环境变量等、文件系统。
  • Entrypoint:入口,是镜像中启动应用的命令
  • 其他:在BaseImage基础上添加依赖、安装系统、完成整个应用的安装和配置。

Dockerfile

Dockerfile就是一个文本文件,其中包含一个一个的指令,用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。

image-20230817165930512

1
2
3
4
5
6
7
8
9
mkdir -p /tmp/docker-demo
cd /tmp/docker-demo
# 利用Xftp上传Dockerfile、jdk8.tar.gz、docker-demo.jar文件到docker-demo文件夹
# 构建镜像,./是Dockerfile文件所在的目录
# -t 给镜像起一个名字
docker build -t javaweb:1.0 ./
docker images
# 构建java项目的镜像
docker run --name web -p 8090:8090 -d javaweb:1.0

Dockerfile文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local

# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar

# 安装JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8

# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin

# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar

案例

基于java:8-alpine镜像,将一个java项目构建为镜像。

Dockerfile

1
2
3
4
5
6
7
8
# 指定基础镜像,java11使用 FROM openjdk:11
FROM openjdk:8-jdk-alpine
# 其他的每个java项目都是重复的,有人已经帮我们做成一个镜像了
COPY ./docker-demo.jar /tmp/app.jar
# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar

将Dockerfile文件放到和jar包一个目录下面

1
2
3
4
5
# ./ 是Dockerfile所在的目录,打包成一个镜像
docker build -t dd ./
docker images
# 构建java项目的镜像
docker run --name docker-demo -p 8090:8090 -d javaweb:1.0

部署前端

1
2
# 将项目放到/root/nginx/html下,对目录和配置文件进行挂载
docker run -d --name nginx -p 18080:18080 -p 18081 -v /root/nginx/html:/usr/share/nginx/html -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf --network heima nginx

五、容器网络互联

默认情况下,所有容器都是以bridge方式连接到Docker的一个虚拟网桥上:

image-20240717215955787

加入自定义网络的容器可以通过容器名互相访问,操作命令如下:

image-20240717220158042

六、DockerCompose

DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个一个创建和运行容器。

Compose文本是一个文本文件,通过指令定义集群中每个容器如何运行。

image-20240717232210744

其中hmall里面的depends_on表示依赖于mysql,到时候会先启动mysql。

image-20240717232929420

image-20240717233058680

命令

1
docker compose [option] [COMMAND]

image-20240717233722401

  1. 准备好docker-compose.yaml文件

  2. 第二步启动

    1
    docker compose up -d
  3. 其他步骤

    1
    2
    3
    4
    5
    docker images; # 查看镜像
    docker ps -a; # 查看所有容器,或docker compose ps 列出所有启动的容器
    # 删除,要先把所有容器删除,才能删除镜像
    docker compose down;
    docker rmi 镜像名称;

七、Docker镜像仓库

镜像仓库有公有和私有的两种形式:

公共仓库:例如Docker官方的Docker Hub,国内也有一些云服务商提供类似于Docker Hub的公开服务,比如网易云镜像服务阿里云镜像服务等。

除了使用公开仓库外,用户还可以在本地搭建私有Docker Registry。企业自己的镜像最好采用Docker Registry来实现。