项目部署(Docker)
本教程使用的是ubuntu(linux发行版本)
安装Docker
步骤1:安装依赖工具
sudo apt install -y ca-certificates curl gnupg lsb-release
作用:Docker 官方源需要这些工具才能正常添加
curl:用来下载文件gnupg:用来验证软件安全性(防止被篡改)ca-certificates:安全证书lsb-release:识别系统版本
步骤2:添加国内阿里云 Docker 镜像密钥
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
步骤 3:添加阿里云 Docker 软件源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
步骤4:安装Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
步骤5:将当前用户添加到Docker用户组中
sudo usermod -aG docker $USER
步骤6:启动和校验
# 启动Docker
systemctl start docker
# 停止Docker
systemctl stop docker
# 重启
systemctl restart docker
# 设置开机自启
systemctl enable docker
# 执行docker ps命令,如果不报错,说明安装启动成功
docker ps
步骤7:配置镜像加速
# 1. 删除旧配置(如果存在)
sudo rm -f /etc/docker/daemon.json
# 2. 写入最新稳定镜像加速源(最靠谱组合)
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirrors.tuna.tsinghua.edu.cn",
"https://mirror.baidubce.com"
]
}
EOF
# 3. 重新加载系统服务配置
sudo systemctl daemon-reload
# 4. 重启 Docker 让配置生效
sudo systemctl restart docker
# 5. 查看是否生效
docker info
了解Docker
Docker 是一个容器化引擎,
作用:把「应用 + 依赖 + 运行环境 + 配置」打包成一个独立、隔离、可移植的单元。
挂载 和 数据卷 Volume
挂载,就是数据卷最终表现出来的行为。
数据卷,就是 Docker 用来实现「挂载」的实际的技术方案
1.挂载:
将「宿主机的某个目录 / 文件」和「容器内部某个目录 / 文件」强行绑定、双向打通 的动作叫做挂载。
挂载之后:
- 改宿主机文件 → 容器里同步变化
- 改容器内文件 → 宿主机同步变化
- 数据实际存放在宿主机,不受容器生命周期影响
2.数据卷:
把容器里的重要数据,挂载 / 持久化到 宿主机 Ubuntu 本地目录,让数据脱离容器独立保存。
特点:
- 数据存在宿主机,删容器不删数据
- 容器坏了、重建、换镜像,数据还在
- 方便备份、迁移、修改配置文件
- 容器和宿主机可以双向读写文件
*宿主机:装了 Docker 的本机,就叫宿主机(就是当前装了ubuntu的那台虚拟机)。所有 Docker 容器都共用它的 Linux 内核。
3.数据卷 / 实现挂载的两种方式
① 绑定挂载:
-v 宿主机绝对路径:容器内路径
注意:本地目录或文件必须以
/或./开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
② 命名数据卷 —— Docker 自动管理
-v 卷名:容器内路径
- Docker 自动创建、管理的数据卷
- 不用管宿主机具体存在哪
- Docker 统一管理存放目录
*数据卷命令:
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker volume create | 创建数据卷 | docker volume create |
| docker volume ls | 查看所有数据卷 | docs.docker.com |
| docker volume rm | 删除指定数据卷 | docs.docker.com |
| docker volume inspect | 查看某个数据卷的详情 | docs.docker.com |
| docker volume prune | 清除数据卷 | docker volume prune |
*注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
镜像和容器
1.镜像
一个只读的、静态的、分层的文件系统模板(实际上就是一堆文件的集合,包含了程序运行需要的系统函数库、环境、配置、依赖。)
2.容器
容器是一种轻量化、可移植、自给自足的软件运行环境,它将应用程序、依赖库、运行环境、配置文件统一打包隔离,依托操作系统内核实现虚拟化。
容器是基于镜像(模板)运行之后,产生的正在运行的实例。一个镜像可以允许无数个容器。
3.公共镜像(官方镜像)
由 Docker 官方、软件官方、开源社区 维护,托管在 Docker Hub / 国内镜像仓库,可直接通过 docker pull 拉取使用的现成基础镜像。
- 开箱即用,无需自己配置环境
- 经过安全审核,稳定性高
- 版本规范:
mysql:8、nginx:alpine、openjdk:17、redis:7 - 用途:中间件、基础运行环境、系统工具
- 国内镜像站:渡渡鸟镜像同步站
# 例如在渡渡鸟中拉取nginx
# 拉取
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/nginx-slim:0.21
# 为镜像标记一个自定义的名字(简化名称) docker tag [镜像源地址] [自定义名]
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/nginx-slim:0.21 nginx-slim:0.21
# 查看镜像
docker images
# 结果:
# IMAGE ID DISK USAGE CONTENT SIZE EXTRA
# nginx-slim:0.21 9f47c9418044 150MB 46.2MB U
4.自定义镜像
开发者基于「公共基础镜像」,通过编写 Dockerfile 定制配置、复制项目代码、安装依赖、指定启动命令,使用 docker build 构建打包,自己制作的业务专属镜像。
- 绑定自身业务代码(前端 dist、后端 jar、Python 项目)
- 环境完全定制,适配项目依赖
- 可私有化部署、迁移、复刻环境
- 只读固化:打包后环境统一,杜绝「本地能跑服务器不能跑」
5.Dockerfile-自定义镜像文件
由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。而这种记录镜像结构的文件就称为Dockerfile。
其中的语法比较多,比较常用的有:
| 指令 | 说明 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM centos:7 |
| ENV | 设置环境变量,可在后面指令使用 | ENV key value |
| COPY | 拷贝本地文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
| RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN yum install gcc |
| EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
| ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |
Dockerfile文件编写好了之后,就可以使用如下命令来构建镜像了
docker build -t 镜像名 .
- -t :是给镜像起名,格式依然是repository:tag的格式,不指定tag时,默认为latest
- . :是指定Dockerfile所在目录,如果就在当前目录,则指定为"."
示例
1.直接在你的 SpringBoot 项目根目录创建文件,文件名必须叫:Dockerfile(无后缀)
# 基础镜像:ubuntu22.04 和你宿主机系统一致
FROM ubuntu:22.04
# 复制你宿主机已解压好的 JDK21 到镜像内部
COPY jdk-21.0.11 /usr/local/java/jdk-21.0.11
# 设置 JDK21 环境变量
ENV JAVA_HOME=/usr/local/java/jdk-21.0.11
ENV PATH=$JAVA_HOME/bin:$PATH
# 阿里云 OSS 密钥环境变量
ENV OSS_ACCESS_KEY_ID=LTAI5tEvdBZ36sBouz2Rpb1a
ENV OSS_ACCESS_KEY_SECRET=mOvi83C4x2gPWY5BeanvU2XZhxI8nj
# 统一UTF-8编码,解决日志/中文乱码
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
# 创建项目工作目录 /tlias-app
RUN mkdir -p /tlias-app
# 进入该目录作为工作空间
WORKDIR /tlias-app
# 复制宿主机的 jar 包 到容器工作目录
COPY tlias-web-managment.jar tlias.jar
# 声明暴露8080端口
EXPOSE 8080
# 容器启动命令:运行SpringBoot jar
ENTRYPOINT ["java","-jar","/tlias-app/tlias.jar"]
2.进入项目根目录(有 Dockerfile 的地方)执行:
docker build -t tlias-app:jdk21 .
网络
1.核心本质
-
Docker 容器默认相互隔离,不同容器默认不能随意通信。
-
Docker 网络作用:控制容器之间、容器与宿主机、容器与外网 的连通规则。
-
核心业务场景:
- 外网 → Nginx(暴露端口)
- Nginx → Java、Java → MySQL(容器内网互通)
2.Docker 三大基础网络模式
bridge 网络
-
默认网络
- 容器运行时如果没有添加到子网就会添加到默认 bridge 网络
- 不同容器之间通过内网 IP 互相访问
- 不支持容器名 DNS 解析,不能用容器名访问
- 容器重启后,内网 IP 会变化,服务会失联
-
自定义子网(常用)
- 由用户手动创建的独立
bridge网络,所有加入同一子网的容器默认互通 - 支持容器名 DNS 解析,可以直接用容器名直接访问(例如
mysql-db:3306) - 容器重启后,内网 IP 可能变化,但容器名不变,通信不受影响
- 网络隔离性强,不同项目可以使用不同子网,互不干扰,更安全
- 支持配置子网网段、网关,便于统一管理
- 与
docker-compose天然适配,compose 会为每个项目自动创建独立子网
- 由用户手动创建的独立
host 网络
- 容器直接共用宿主机网卡,无网络隔离
- 容器没有独立 IP,端口直接占用宿主机端口
- 优点:性能高;缺点:隔离性差、端口容易冲突,生产少用
none 网络
- 容器完全禁用所有网络,断网隔离
- 仅用于极高安全隔离场景,业务项目基本不用
3.示例:(搭建自定义子网):
# 创建自定义子网
docker network create my-project-net
# 查看所有网络
docker network ls
# 输出结果
# NETWORK ID NAME DRIVER SCOPE
# 610feabef0e5 bridge bridge local
# 11f0a2f6967a host host local
# a6e715d6ddb8 my-project-net bridge local
# 505930335e66 none null local
# 运行容器并加入子网
docker run --network my-project-net ...
# 给已有容器添加网络
docker network connect my-project-net 容器名
*常见命令
| 命令 | 说明 |
|---|---|
| docker network create | 创建一个网络 |
| docker network ls | 查看所有网络 |
| docker network rm | 删除指定网络 |
| docker network prune | 清除未使用的网络 |
| docker network connect | 使指定容器连接加入某网络 |
| docker network disconnect | 使指定容器连接离开某网络 |
| docker network inspect | 查看网络详细信息 |
示例:部署项目到docker容器
准备工作
1.关闭宿主机自带服务,释放端口
避免和 Docker 容器端口冲突:
# 停止并禁用宿主机 Nginx
sudo systemctl stop nginx
sudo systemctl disable nginx
# 停止并禁用宿主机 MySQL(根据实际服务名调整)
sudo systemctl stop mysql
sudo systemctl disable mysql
# 验证端口是否释放
sudo lsof -i:80
sudo lsof -i:3306
若命令无输出,说明端口已释放。
2.安装 Docker(Ubuntu 系统)
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER # 将当前用户添加到docker用户组
newgrp docker
docker --version
3.创建自定义 Docker 子网
# 创建自定义子网(所有容器都加入这个网络)
docker network create my-project-net
# 验证子网创建成功
docker network ls
数据库部署
1.创建宿主机数据目录(持久化数据)
mkdir -p /data/mysql # 使用宿主机的/data/mysql作为数据卷
2.安装mysql镜像
# 使用第三方镜像源安装msyql镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/gcr.io/ml-pipeline/mysql:8.0.26
# 打标签
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/gcr.io/ml-pipeline/mysql:8.0.26 mysql:8.0
# 查看是否安装成功
docker images
3.运行mysql容器
docker run -d \ # -d:在后代运行,不影响命令行窗口
--name mysql-db \ # 容器名称
--network my-project-net \ # 加入自定义子网
--restart always \ # 重启策略:当非人为关闭时会自动重启
-p 3306:3306 \ # 将容器内的3306端口映射到宿主机的3306端口
-v /data/mysql:/var/lib/mysql \ # 挂载数据卷
-e MYSQL_ROOT_PASSWORD=1234 \ # 设置root用户密码为1234
-e TZ=Asia/Shanghai \ # 设置mysql的时区为亚洲/上海(影响数据库内部的时间)
mysql:8.0 # 使用刚才安装的mysql镜像
- 注意需要关闭宿主机的3306端口的防火墙
4.使用DataGrip(数据库工具)连接数据库
(1)连接数据库
主机:192.168.100.128 # ubuntu的ip地址,通过ip addr 查看
用户:root
密码:1234
URL:jdbc:mysql://192.128.100.128:3306
(2)执行项目的sql脚本
服务端部署
1.修改项目数据库配置
spring:
datasource:
url: jdbc:mysql://mysql-db:3306/tlias # 同一子网内通过容器名连接
username: root
password: 1234
2.安装ubuntu:22.04镜像(自定义镜像会使用)
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ubuntu:22.04
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/ubuntu:22.04 ubuntu:22.04
3.构建自定义的java运行镜像(Dockerfile)
(1)在指定目录(这里是~/dist/)下准备一些文件
- 解压后的jdk包,例如:jdk-21.0.11目录
- 项目jar包,例如:tlias-management.jar
- Dockfile文件(如下)
# 基础镜像:ubuntu22.04
FROM ubuntu:22.04
# 复制宿主机已解压好的 JDK21 到镜像内部
COPY jdk-21.0.11 /usr/local/java/jdk-21.0.11
# 设置 JDK21 环境变量
ENV JAVA_HOME=/usr/local/java/jdk-21.0.11
ENV PATH=$JAVA_HOME/bin:$PATH
# 阿里云 OSS 密钥环境变量
ENV OSS_ACCESS_KEY_ID=LTAI5tEvdBZ36sBouz2Rpb1a
ENV OSS_ACCESS_KEY_SECRET=mOvi83C4x2gPWY5BeanvU2XZhxI8nj
# 统一UTF-8编码,解决日志/中文乱码
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
# 创建项目工作目录 /tlias-app
RUN mkdir -p /tlias-app
# 进入该目录作为工作空间
WORKDIR /tlias-app
# 复制宿主机的 jar 包 到容器工作目录
COPY tlias-web-managment.jar tlias.jar
# 声明暴露8080端口
EXPOSE 8080
# 容器启动命令:运行SpringBoot jar
ENTRYPOINT ["java","-jar","/tlias-app/tlias.jar"]
(2)构建镜像
docker build -t tlias-app:jdk21 .
4.运行自定义镜像的容器
docker run -d \
--name tlias-app \
--network my-project-net \
-p 8080:8080 \
--restart always \
tlias-app:jdk21
前端部署
1.准备文件放到数据卷中
-
/data/nginx/html/:前端文件
-
/data/nginx/cnof/:nginx.conf
#user nobody; worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; client_max_body_size 10m; location / { root html; index index.html index.htm; try_files $uri $uri/ /index.html; } location ^~ /api/ { rewrite ^/api/(.*)$ /$1 break; proxy_pass http://tlias-app:8080; # 注意这里的使用子网连接到spring服务 } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
2.安装nginx镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/nginx-slim:0.21
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/nginx-slim:0.21 nginx-slim:0.21
3.运行容器
docker run -d \ # 后台运行容器
--name nginx-tlias \ # 容器名叫 nginx-tlias
-v /data/nginx/html:/usr/share/nginx/html \ # 挂载前端页面
-v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \ # 挂载配置文件
--network my-project-net \ # 加入自定义子网(能和java、mysql通信)
-p 80:80 \ # 端口映射 宿主机80 → 容器80
nginx-slim:0.21 # 使用docker镜像
访问网页
在windows系统中的浏览器导航栏输入宿主机ip就可以访问了 到此项目在docker中就部署成功了
*Docker常见命令
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker pull | 拉取镜像 | docker pull |
| docker push | 推送镜像到DockerRegistry | docker push |
| docker images | 查看本地镜像 | docker images |
| docker rmi | 删除本地镜像 | docker rmi |
| docker run | 创建并运行容器(不能重复创建) | docker run |
| docker stop | 停止指定容器 | docker stop |
| docker start | 启动指定容器 | docker start |
| docker restart | 重新启动容器 | docker restart |
| docker rm | 删除指定容器 | docs.docker.com |
| docker ps | 查看容器 | docker ps |
| docker logs | 查看容器运行日志 | docker logs |
| docker exec | 进入容器 | docker exec |
| docker save | 保存镜像到本地压缩文件 | docker save |
| docker load | 加载本地压缩文件到镜像 | docker load |
| docker inspect | 查看容器详细信息 | docker inspect |