前言

在学习 Linux 操作系统和项目部署时,我们常遇到命令繁多、软件安装复杂、环境依赖冲突等问题。尤其在微服务时代,成百上千台服务器的部署运维更是挑战。Docker 技术的出现,通过容器化解决了环境隔离与快速部署的问题,让项目部署变得简单高效。

本文基于 Ubuntu 24.04 LTS 系统,整理 Docker 核心知识点,包括基础命令、数据卷、镜像构建、网络配置及项目部署,并补充实用扩展内容。

1. 快速入门

1.1 安装 Docker

Docker 支持主流操作系统,但安装方式因系统而异。以 Ubuntu 24.04 LTS 为例,可直接参考官方安装文档:https://docs.docker.com/engine/install/ubuntu/

image

按照文档提示逐步执行命令即可,也可参考视频教程操作:https://www.bilibili.com/video/BV183B1Y2EGk/?spm_id_from=333.337.search-card.all.click&vd_source=ffdc8ef30147923fee0d363c8e4b12bb

对于其他系统(如 CentOS),在官方文档中选择对应系统的安装指南即可。

Docker 默认从官方仓库(Docker Hub)拉取镜像,由于该仓库服务器位于国外,国内用户直接访问时可能因网络链路长、带宽限制或地域访问策略,出现拉取超时、速度卡顿等问题。针对这类问题,可采用以下解决方案:

  • 镜像加速:通过国内云厂商(如阿里云、腾讯云等)提供的 “镜像加速器”,将拉取请求转发至国内节点,大幅提升拉取速度。
  • VPN:通过合规的虚拟专用网络连接国外网络,绕开地域限制,直接访问 Docker Hub

Ubuntu 24.04 通过 /etc/docker/daemon.json 配置加速,以阿里云为例:

  1. 登录阿里云容器镜像服务,获取专属加速地址(如 https://xxxx.mirror.aliyuncs.com

  2. 创建配置文件:

    1
    2
    3
    4
    5
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
    "registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
    }
    EOF
  3. 重启 Docker 使配置生效:

    1
    2
    sudo systemctl daemon-reload
    sudo systemctl restart docker

1.2 部署 MySQL(Docker 方式对比传统方式)

使用 Docker 部署软件比传统方式更高效。以 MySQL 为例:

传统部署 MySQL 步骤

  • 搜索并下载 Ubuntu 版本的 MySQL 安装包(mysql-server_8.0_amd64.deb
  • 手动解决依赖冲突(如 libmysqlclient-dev 等)
  • 执行 dpkg -i 安装并通过 mysql_secure_installation 配置
  • 调整 /etc/mysql/my.cnf 配置文件

Docker 部署 MySQL 步骤(仅需 1 条命令)

1
2
3
4
5
6
sudo docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql

镜像名称格式REPOSITORY:TAG(如 mysql:8.0,未指定 TAG 则默认 latest

运行效果如图:

MySQL安装完毕!现在通过任意客户端工具即可连接到MySQL啦

1.3 核心概念解析

概念 英文 说明
镜像 Image 包含应用程序、依赖环境、配置文件的只读模板(如 MySQL 镜像含 MySQL 及运行库)
容器 Container 镜像运行后的实例,是独立隔离的运行环境
镜像仓库 Registry 存储镜像的服务器(官方:DockerHub;第三方:阿里云 / 华为云;私有:企业自建)

1.4 命令解读(部署 MySQL 命令拆解)

1
2
3
4
5
6
sudo docker run -d \          # 创建并启动容器,-d 表示后台运行
--name mysql \ # 容器命名为 mysql(自定义)
-p 3306:3306 \ # 端口映射:宿主机3306 → 容器内3306(容器隔离需映射才能外部访问)
-e TZ=Asia/Shanghai \ # 环境变量:设置容器时区为上海
-e MYSQL_ROOT_PASSWORD=123 \# 环境变量:设置 MySQL root 密码
mysql # 镜像名称(默认拉取 latest 版本,可指定如 mysql:8.0)

镜像名称格式REPOSITORY:TAG(如 mysql:8.0,未指定 TAG 则默认 latest

总结一下:

Docker本身包含一个后台服务,我们可以利用Docker命令告诉Docker服务,帮助我们快速部署指定的应用。Docker服务部署应用时,首先要去搜索并下载应用对应的镜像,然后根据镜像创建并允许容器,应用就部署完成了。

用一幅图标示如下:

2. Docker 基础

2.1 常见命令(Ubuntu 24.04 需加 sudo

命令 说明 示例
docker pull 拉取镜像到本地 sudo docker pull nginx:latest
docker images 查看本地所有镜像 sudo docker images
docker rmi 删除本地镜像(需先删依赖容器) sudo docker rmi mysql:latest
docker run 创建并启动容器(不可重复创建同名容器) sudo docker run -d --name nginx nginx
docker stop 停止运行中的容器 sudo docker stop mysql
docker start 启动已停止的容器 sudo docker start mysql
docker restart 重启容器 sudo docker restart mysql
docker rm 删除容器(运行中需加 -f 强制删除) sudo docker rm -f mysql
docker ps 查看运行中的容器(-a 查看所有) sudo docker ps -a
docker logs 查看容器运行日志(-f 实时跟踪) sudo docker logs -f mysql
docker exec 进入容器内部(-it 交互模式) sudo docker exec -it mysql bash
docker save 保存镜像为本地压缩包 sudo docker save -o nginx.tar nginx
docker load 加载本地压缩包为镜像 sudo docker load -i nginx.tar
docker inspect 查看容器 / 镜像详细信息 sudo docker inspect mysql

用一副图来表示这些命令的关系:

补充:

默认情况下,每次重启虚拟机我们都需要手动启动Docker和Docker中的容器。通过命令可以实现开机自启:

1
2
3
4
5
# Docker开机自启
sudo systemctl enable docker

# Docker容器开机自启
sudo docker update --restart=always [容器名/容器id]

2.1.2 演示(以 Nginx 为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 第1步,去DockerHub查看nginx镜像仓库及相关信息

# 第2步,拉取Nginx镜像
sudo docker pull nginx

# 第3步,查看镜像
sudo docker images
# 结果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB

# 第4步,创建并运行Nginx容器
sudo docker run -d --name nginx -p 80:80 nginx

# 第5步,查看运行中容器
sudo docker ps
# 也可以加格式化方式访问,格式会更加清爽
sudo docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

# 第6步,访问网页,地址:http://localhost

# 第7步,停止容器
sudo docker stop nginx

# 第8步,查看所有容器
sudo docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

# 第9步,再次启动nginx容器
sudo docker start nginx

# 第10步,再次查看容器
sudo docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

# 第11步,查看容器详细信息
sudo docker inspect nginx

# 第12步,进入容器,查看容器内目录
sudo docker exec -it nginx bash
# 或者,可以进入MySQL
sudo docker exec -it mysql mysql -uroot -p

# 第13步,删除容器
sudo docker rm nginx
# 发现无法删除,因为容器运行中,强制删除容器
sudo docker rm -f nginx

2.1.3 命令别名配置(简化操作)

Ubuntu 24.04 可通过修改 ~/.bashrc 设置别名:

1
2
3
4
5
6
7
# 编辑配置文件(普通用户用 ~/.bashrc,root 用户用 /root/.bashrc)
vi ~/.bashrc
# 添加以下内容
alias dps='sudo docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
alias dis='sudo docker images'
# 使别名生效
source ~/.bashrc

2.2 数据卷(容器与宿主机数据互通)

容器默认隔离,数据卷可实现容器内目录与宿主机目录的映射,解决数据持久化、配置修改等问题。

2.2.1 什么是数据卷

数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。

以 Nginx 为例,其 html(静态资源)和 conf(配置文件)目录需与宿主机关联,数据卷挂载逻辑如下:

在上图中:

  • 创建了两个数据卷:confhtml
  • Nginx 容器内部的 conf 目录和 html 目录分别与两个数据卷关联
  • 数据卷分别指向宿主机的 /var/lib/docker/volumes/conf/_data/var/lib/docker/volumes/html/_data

2.2.2 数据卷命令

命令 说明 示例
docker volume create 创建数据卷 sudo docker volume create nginx-html
docker volume ls 查看所有数据卷 sudo docker volume ls
docker volume rm 删除指定数据卷 sudo docker volume rm nginx-html
docker volume inspect 查看数据卷详情 sudo docker inspect nginx-html
docker volume prune 清除未使用的数据卷 sudo docker volume prune

2.2.3 实战:挂载数据卷到 Nginx

1
2
3
4
5
6
7
8
9
10
# 创建并启动 Nginx 容器,挂载数据卷 nginx-html 到容器内 /usr/share/nginx/html
sudo docker run -d --name nginx -p 80:80 -v nginx-html:/usr/share/nginx/html nginx

# 查看数据卷详情(获取宿主机映射路径)
sudo docker inspect nginx-html
# 宿主机路径通常为 /var/lib/docker/volumes/nginx-html/_data

# 修改宿主机文件,容器内自动同步
sudo vi /var/lib/docker/volumes/nginx-html/_data/index.html
# 访问 localhost 验证效果

2.2.4 实战:直接挂载宿主机目录(更灵活)

Ubuntu 24.04 支持直接将宿主机目录挂载到容器,无需数据卷中间层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1. 宿主机创建目录(以 MySQL 为例)
mkdir -p ~/mysql/{conf,data,init}

# 2. 复制配置文件到 conf 目录、初始化 SQL 到 init 目录
【此处需补充图片:课前资料中 mysql 目录结构截图(含 conf、data、init 子目录)】
【此处需补充图片:init 目录下初始化 SQL 脚本和 conf 目录下配置文件的截图】

# 3. 启动 MySQL 容器,挂载宿主机目录
sudo docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v ~/mysql/data:/var/lib/mysql \ # 数据持久化
-v ~/mysql/conf:/etc/mysql/conf.d \ # 配置文件挂载
-v ~/mysql/init:/docker-entrypoint-initdb.d \ # 初始化脚本挂载
mysql

# 4. 查看宿主机目录,确认 data 自动创建
ls -l ~/mysql
# 结果:
总用量 4
drwxr-xr-x. 2 root root 20 5月 19 15:11 conf
drwxr-xr-x. 7 polkitd root 4096 5月 19 15:11 data
drwxr-xr-x. 2 root root 23 5月 19 15:11 init

# 5. 验证数据库初始化结果
sudo docker exec -it mysql mysql -uroot -p123
# 查看编码(应为 utf8mb4)
show variables like "%char%";
# 查看数据库(应有 hmall 库)
show databases;

2.3 自定义镜像(Dockerfile 实战)

当现有镜像无法满足需求时,可通过 Dockerfile 构建自定义镜像。

2.3.1 镜像结构

镜像采用 “分层叠加” 机制,每一层对应 Dockerfile 中的一条指令,复用性强(如 Java 镜像可基于官方 JDK 镜像叠加)。

2.3.2 Dockerfile 核心指令

指令 说明 示例
FROM 指定基础镜像(必须为第一条指令) FROM openjdk:11.0-jre-buster
ENV 设置环境变量 ENV TZ=Asia/Shanghai
COPY 拷贝本地文件到镜像 COPY ./hm-service.jar /app.jar
RUN 执行 Linux 命令(构建时运行) RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
EXPOSE 声明容器监听端口(仅说明,不映射) EXPOSE 8080
ENTRYPOINT 容器启动命令(不可被覆盖) ENTRYPOINT ["java", "-jar", "/app.jar"]

2.3.3 实战:构建 Java 应用镜像

  1. 准备文件:将 docker-demo.jar 和 Dockerfile 放入 ~/demo 目录

  2. 编写 Dockerfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 基础镜像(含 JRE 环境)
    FROM openjdk:11.0-jre-buster
    # 设置时区
    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
    # 拷贝 jar 包
    COPY ./docker-demo.jar /app.jar
    # 声明端口
    EXPOSE 8080
    # 启动命令
    ENTRYPOINT ["java", "-jar", "/app.jar"]
  3. 构建镜像

    1
    2
    3
    4
    # 进入镜像目录
    cd /root/demo
    # 开始构建
    docker build -t docker-demo:1.0 .

    结果:

    查看镜像列表:

    1
    2
    3
    4
    5
    6
    7
    # 查看镜像列表:
    docker images
    # 结果
    REPOSITORY TAG IMAGE ID CREATED SIZE
    docker-demo 1.0 d6ab0b9e64b9 27 minutes ago 327MB
    nginx latest 605c77e624dd 16 months ago 141MB
    mysql latest 3218b38490ce 17 months ago 516MB
  4. 运行自定义镜像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 1.创建并运行容器
    docker run -d --name dd -p 8080:8080 docker-demo:1.0
    # 2.查看容器
    dps
    # 结果
    CONTAINER ID IMAGE PORTS STATUS NAMES
    78a000447b49 docker-demo:1.0 0.0.0.0:8080->8080/tcp, :::8090->8090/tcp Up 2 seconds dd
    f63cfead8502 mysql 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp Up 2 hours mysql

    # 3.访问
    curl localhost:8080/hello/count
    # 结果:
    <h5>欢迎访问黑马商城, 这是您第1次访问<h5>

2.4 网络(容器间通信)

Docker 默认网络隔离,自定义网络可实现容器通过 “别名” 互通,避免依赖动态 IP。

2.4.1 常见网络命令

命令 说明 示例
docker network create 创建自定义网络 sudo docker network create hmall-net
docker network ls 查看所有网络 sudo docker network ls
docker network connect 让容器加入网络 sudo docker network connect hmall-net mysql
docker network disconnect 让容器离开网络 sudo docker network disconnect hmall-net mysql

2.4.2 实战:自定义网络实现容器互通

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 创建自定义网络
sudo docker network create hmall-net

# 2. 启动 MySQL 并加入网络(指定别名 db)
sudo docker run -d --name mysql --network hmall-net --alias db -e MYSQL_ROOT_PASSWORD=123 mysql

# 3. 启动 Java 应用并加入同一网络
sudo docker run -d --name dd --network hmall-net -p 8080:8080 hmall:1.0

# 4. 验证通信(进入 Java 容器 ping MySQL)
sudo docker exec -it hmall bash
ping db # 可通过别名 db 或容器名 mysql 访问

3. 项目部署实战(黑马商城)

3.1 项目结构

课前资料提供的项目包含:

  • 后端:hmall(Java 项目,端口 8080)
  • 前端:hmall-portal(用户端,端口 18080)、hmall-admin(管理端,端口 18081)
项目 容器名 端口 备注
hmall hmall 8080 后端 API 入口
hmall-portal nginx 18080 用户端前端入口
hmall-admin nginx 18081 管理端前端入口
MySQL mysql 3306 数据库

3.2 部署步骤

3.2.1 部署后端 Java 项目

  1. 打包项目:用 IDEA 打包 hm-service 模块,得到 hm-service.jar

  2. 上传文件:将 hm-service.jar 和 Dockerfile 上传到 Ubuntu 24.04 的 ~/ 目录

  3. 构建镜像并启动

    1
    2
    3
    4
    # 构建镜像
    sudo docker build -t hmall .
    # 启动容器(加入自定义网络)
    sudo docker run -d --name hmall --network hmall-net -p 8080:8080 hmall
  4. 验证:访问 http://localhost:8080/search/list

3.2.2 部署前端(Nginx 代理)

  1. 准备文件:把整个nginx目录上传到虚拟机的~目录下:

  2. 启动 Nginx 容器

    1
    2
    3
    4
    5
    6
    7
    8
    sudo docker run -d \
    --name nginx \
    -p 18080:18080 \
    -p 18081:18081 \
    -v ~/nginx/html:/usr/share/nginx/html \
    -v ~/nginx/nginx.conf:/etc/nginx/nginx.conf \
    --network hmall-net \
    nginx
  3. 验证

    • 用户端:

      1
      http://localhost:18080

    • 管理端:http://localhost:18081

3.3 Docker Compose(批量部署多容器)

3.3.1 基本语法

docker-compose.yml 文件通过 “服务(service)” 定义容器配置,与 docker run 参数对应关系如下:

docker run 参数 docker compose 指令 说明
--name container_name 容器名称
-p ports 端口映射
-e environment 环境变量
-v volumes 数据卷 / 目录挂载
--network networks 网络配置

3.3.2 黑马商城 Compose 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
version: "3.8"

services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
- "./mysql/init:/docker-entrypoint-initdb.d"
networks:
- hm-net
hmall:
build:
context: .
dockerfile: Dockerfile
container_name: hmall
ports:
- "8080:8080"
networks:
- hm-net
depends_on:
- mysql
nginx:
image: nginx
container_name: nginx
ports:
- "18080:18080"
- "18081:18081"
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
- "./nginx/html:/usr/share/nginx/html"
depends_on:
- hmall
networks:
- hm-net
networks:
hm-net:
name: hmall-net

3.3.3 基础命令

Docker Compose 命令的基本语法为:

1
docker compose [OPTIONS] [COMMAND]
类型 参数 / 指令 说明
Options -f 指定 docker-compose.yml 文件的路径和名称(默认查找当前目录下的该文件)
Options -p 指定 ** 项目(project)** 名称,项目是 docker-compose.yml 中多个服务(service)的集合
Commands up 创建并启动所有定义的服务容器(-d 表示后台启动
Commands down 停止并移除所有容器、网络(默认保留挂载的数据卷)
Commands ps 列出所有启动的容器
Commands logs 查看指定容器的运行日志(示例:docker compose logs 容器名
Commands stop 停止容器
Commands start 启动已停止的容器
Commands restart 重启容器
Commands top 查看容器内运行的进程
Commands exec 在运行中的容器内执行命令(示例:docker compose exec 容器名 bash
教学演示:部署黑马商城项目
步骤 1:进入项目根目录
1
cd ~
步骤 2:清理旧容器与资源
1
2
3
4
5
6
7
8
# 强制删除所有正在运行的Docker容器
sudo docker rm -f $(sudo docker ps -qa)

# 删除旧的hmall镜像(若存在需更新的情况)
sudo docker rmi hmall

# 清空MySQL数据目录(如需重新初始化数据库)
rm -rf mysql/data
步骤 3:启动所有服务(后台运行)
1
sudo docker compose up -d

执行结果示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[+] Building 15.5s (8/8) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 358B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/openjdk:11.0-jre-buster 15.4s
=> [1/3] FROM docker.io/library/openjdk:11.0-jre-buster@sha256:3546a17e6fb4ff4fa681c3 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 98B 0.0s
=> CACHED [2/3] RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 0.0s
=> CACHED [3/3] COPY hm-service.jar /app.jar 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:32eebee16acde22550232f2eb80c69d2ce813ed099640e4cfed2193f71 0.0s
=> => naming to docker.io/library/root-hmall 0.0s
[+] Running 4/4
✔ Network hmall Created 0.2s
✔ Container mysql Started 0.5s
✔ Container hmall Started 0.9s
✔ Container nginx Started 1.5s
步骤 4:查看镜像列表
1
sudo docker compose images

执行结果示例

1
2
3
4
CONTAINER           REPOSITORY          TAG                 IMAGE ID            SIZE
hmall root-hmall latest 32eebee16acd 362MB
mysql mysql latest 3218b38490ce 516MB
nginx nginx latest 605c77e624dd 141MB
步骤 5:查看运行中容器
1
sudo docker compose ps

执行结果示例

1
2
3
4
NAME                IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
hmall root-hmall "java -jar /app.jar" hmall 54 seconds ago Up 52 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp
mysql mysql "docker-entrypoint.s…" mysql 54 seconds ago Up 53 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp
nginx nginx "/docker-entrypoint.…" nginx 54 seconds ago Up 52 seconds 80/tcp, 0.0.0.0:18080-18081->18080-18081/tcp, :::18080-18081->18080-18081/tcp
步骤 6:验证项目访问

打开浏览器,访问后端接口(将 yourIp 替换为 Ubuntu 主机的实际 IP 地址):

1
http://yourIp:8080

若能正常加载页面或返回接口数据,说明 Docker Compose 部署成功。