项目部署(Docker)

3 阅读4分钟

项目部署(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 本地目录,让数据脱离容器独立保存

特点:

  1. 数据存在宿主机,删容器不删数据
  2. 容器坏了、重建、换镜像,数据还在
  3. 方便备份、迁移、修改配置文件
  4. 容器和宿主机可以双向读写文件

*宿主机:装了 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:8nginx:alpineopenjdk:17redis: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.核心本质
  1. Docker 容器默认相互隔离,不同容器默认不能随意通信。

  2. Docker 网络作用:控制容器之间、容器与宿主机、容器与外网 的连通规则

  3. 核心业务场景:

    • 外网 → Nginx(暴露端口)
    • Nginx → Java、Java → MySQL(容器内网互通)
2.Docker 三大基础网络模式

bridge 网络

  • 默认网络

    1. 容器运行时如果没有添加到子网就会添加到默认 bridge 网络
    2. 不同容器之间通过内网 IP 互相访问
    3. 不支持容器名 DNS 解析,不能用容器名访问
    4. 容器重启后,内网 IP 会变化,服务会失联
  • 自定义子网(常用)

    1. 由用户手动创建的独立 bridge 网络,所有加入同一子网的容器默认互通
    2. 支持容器名 DNS 解析,可以直接用容器名直接访问(例如 mysql-db:3306
    3. 容器重启后,内网 IP 可能变化,但容器名不变,通信不受影响
    4. 网络隔离性强,不同项目可以使用不同子网,互不干扰,更安全
    5. 支持配置子网网段、网关,便于统一管理
    6. 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推送镜像到DockerRegistrydocker 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