一、引言
在当今的软件开发与运维领域,快速、高效地部署和管理应用是至关重要的。Docker 作为一款强大的容器化技术工具,能够帮助开发者和运维人员轻松构建、运行和管理应用,极大地提高工作效率。本教学文档将深入介绍 Docker 的相关知识,涵盖从基础概念到项目部署的全流程,助力读者快速掌握 Docker 技术并应用于实际工作中。
二、Docker 基础概念
(一)镜像(Image)
- 定义:将应用所需的函数库、依赖、配置等与应用一起打包得到的文件包。镜像包含了应用运行所需要的完整环境,包括操作系统、系统函数库、应用程序及其配置等,它是创建容器的基础。
- 命名规范:镜像名称一般由两部分组成:
[repository]:[tag]
。其中repository
是镜像名,tag
是镜像的版本。若未指定tag
,默认是latest
,代表最新版本的镜像,例如mysql:5.7
,mysql
是repository
,5.7
是tag
。
(二)容器(Container)
- 定义:为每个镜像的应用进程创建的隔离运行环境。容器基于镜像创建,是镜像的运行实例,多个容器可以共享同一个镜像。容器之间相互隔离,拥有独立的文件系统、网络环境和进程空间,保证了应用运行的独立性和安全性。
- 与镜像的关系:镜像是静态的文件包,用于创建容器;容器是镜像的动态运行实例,通过运行镜像来启动容器,容器中的应用在隔离环境中运行,与宿主机和其他容器相互隔离。
(三)镜像仓库(Registry)
- 定义:存储和管理镜像的服务平台。它提供了镜像的存储、分发和共享功能,方便用户获取和使用各种镜像。
- Docker Hub:目前最大的公共镜像仓库,包含了各种常见的应用镜像,如
mysql
、nginx
、java
等。用户可以在 Docker Hub 上搜索、下载和上传镜像,也可以基于官方镜像进行定制和扩展。
三、部署 MySQL
(一)传统方式安装 MySQL 的痛点
在传统的 Linux 系统中安装 MySQL,需要执行一系列复杂的操作,包括卸载系统自带的 MySQL 相关组件(如mariadb-libs
)、下载 MySQL 安装包(从官网选择合适的版本和操作系统类型)、解压缩安装包、安装依赖包(如net-tools
、openssl-devel
等)、安装 MySQL 服务等。这个过程涉及众多命令,安装包的下载和依赖处理也较为繁琐,容易出错,且安装过程耗时较长。
(二)使用 Docker 部署 MySQL
- 前提条件:确保虚拟机已经安装 Docker,且网络连接正常。
- 部署命令:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql
- 命令解读:
docker run
:创建并运行一个容器。-d
:让容器在后台运行,不占用当前终端的输入输出,用户可以继续在终端执行其他命令。--name mysql
:给容器起名为mysql
,容器名在当前 Docker 环境中必须唯一,方便后续对该容器进行管理和操作。-p 3306:3306
:设置端口映射,将宿主机的 3306 端口映射到容器内的 3306 端口。这样,外部应用就可以通过宿主机的 3306 端口访问容器内的 MySQL 服务。-e TZ=Asia/Shanghai
:设置容器内的时区为上海时区,确保时间相关的操作和应用逻辑正常运行。-e MYSQL_ROOT_PASSWORD=123
:设置 MySQL 的 root 用户密码为123
,用于登录 MySQL 数据库。mysql
:指定运行的镜像名称,这里使用的是 Docker Hub 上的官方mysql
镜像,若本地没有该镜像,Docker 会自动从 Docker Hub 下载。
四、Docker 常见命令
(一)镜像操作命令
- docker pull:从镜像仓库拉取镜像到本地。例如,拉取
nginx
镜像:docker pull nginx
。 - docker push:将本地镜像推送到镜像仓库,需要先登录到镜像仓库。
- docker images:查看本地已有的镜像列表,显示镜像的名称、标签、镜像 ID、创建时间和大小等信息。
- docker rmi:删除本地指定的镜像,例如
docker rmi nginx:latest
删除本地的nginx:latest
镜像。
(二)容器操作命令
- docker run:创建并运行容器,前面部署 MySQL 时已详细介绍。
- docker stop:停止运行中的容器,例如
docker stop mysql
停止名为mysql
的容器。 - docker start:启动已停止的容器,
docker start mysql
启动名为mysql
的容器。 - docker ps:查看当前正在运行的容器列表,显示容器的 ID、名称、运行状态、创建时间、端口映射等信息。加上
-a
参数可以查看所有容器(包括已停止的容器)。 - docker rm:删除指定的容器,容器必须是停止状态才能删除,例如
docker rm mysql
删除名为mysql
的容器。 - docker logs:查看容器的日志输出,帮助调试和监控容器内应用的运行情况,如
docker logs mysql
查看mysql
容器的日志。 - docker exec:在运行中的容器内执行命令,例如
docker exec -it mysql bash
在mysql
容器内执行bash
命令,进入容器的命令行界面,-it
参数用于保持标准输入输出的交互性。
(三)数据卷操作命令
- docker volume create:创建数据卷,例如
docker volume create my_volume
创建名为my_volume
的数据卷。 - docker volume ls:查看所有数据卷,显示数据卷的名称、驱动等信息。
- docker volume rm:删除指定的数据卷,
docker volume rm my_volume
删除名为my_volume
的数据卷。 - docker volume inspect:查看某个数据卷的详细信息,包括数据卷的挂载点、驱动选项等。
- docker volume prune:清除未使用的数据卷,释放磁盘空间。
(四)网络操作命令
- docker network create:创建一个自定义网络,如
docker network create my_network
创建名为my_network
的网络。 - docker network ls:查看所有网络,包括默认的
bridge
网络和自定义网络。 - docker network rm:删除指定的网络,
docker network rm my_network
删除名为my_network
的网络。 - docker network prune:清除未使用的网络。
- docker network connect:使指定容器连接加入某网络,
docker network connect my_network mysql
将mysql
容器连接到my_network
网络。 - docker network disconnect:使指定容器连接离开某网络。
- docker network inspect:查看网络的详细信息,包括网络的子网、网关、连接的容器等。
五、数据卷(Volume)
(一)数据卷的概念
数据卷是一个虚拟目录,它是容器内目录与宿主机目录之间映射的桥梁。通过数据卷,可以方便地在宿主机和容器之间共享数据,实现对容器内文件的操作和数据的持久化存储,即使容器被删除,数据卷中的数据依然存在。
(二)数据卷的使用场景
- 容器内文件操作:在容器运行过程中,需要修改容器内的配置文件或数据文件时,可以通过数据卷将宿主机的目录挂载到容器内,直接在宿主机上进行修改,容器内的文件也会同步更新。
- 数据持久化:对于一些有数据存储需求的应用,如数据库,将数据目录挂载到数据卷上,保证数据不会因为容器的重启或删除而丢失。
(三)挂载数据卷的方法
在执行docker run
命令时,使用-v
参数进行数据卷挂载,格式为-v 数据卷名:容器内目录
或-v 本地目录:容器内目录
。当创建容器时,如果挂载的数据卷不存在,Docker 会自动创建数据卷。例如,将宿主机的/root/mysql/data
目录挂载到mysql
容器内的/var/lib/mysql
目录:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v /root/mysql/data:/var/lib/mysql \
mysql
(四)案例 - 利用 Nginx 容器部署静态资源
- 需求:创建 Nginx 容器,修改容器内
html
目录下的index.html
文件内容,并将静态资源部署到 Nginx 的html
目录。 - 步骤:
- 创建数据卷:
docker volume create nginx_volume
。 - 创建 Nginx 容器并挂载数据卷:
- 创建数据卷:
docker run -d \
--name nginx \
-p 80:80 \
-v nginx_volume:/usr/share/nginx/html \
nginx
- 在宿主机上找到数据卷对应的目录(可通过
docker volume inspect nginx_volume
查看挂载点),在该目录下创建或修改index.html
文件,容器内的/usr/share/nginx/html/index.html
文件会同步更新。 - 将静态资源拷贝到数据卷对应的目录,即可完成静态资源的部署。
(五)案例 - mysql 容器的数据挂载
- 需求:基于宿主机目录实现 MySQL 数据目录、配置文件、初始化脚本的挂载。
- 步骤:
- 挂载数据目录:
-v /root/mysql/data:/var/lib/mysql
,将宿主机的/root/mysql/data
目录挂载到容器内的/var/lib/mysql
目录,用于存储 MySQL 的数据文件。 - 挂载配置文件目录:
-v /root/mysql/conf:/etc/mysql/conf.d
,将宿主机的/root/mysql/conf
目录挂载到容器内的/etc/mysql/conf.d
目录,用于存放 MySQL 的配置文件。 - 挂载初始化脚本目录:
-v /root/mysql/init:/docker-entrypoint-initdb.d
,将宿主机的/root/mysql/init
目录挂载到容器内的/docker-entrypoint-initdb.d
目录,并在该目录下放置初始化 SQL 脚本,容器启动时会自动执行这些脚本。
完整的docker run
命令如下:
- 挂载数据目录:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v /root/mysql/data:/var/lib/mysql \
-v /root/mysql/conf:/etc/mysql/conf.d \
-v /root/mysql/init:/docker-entrypoint-initdb.d \
mysql
六、自定义镜像
(一)自定义镜像的概念
自定义镜像就是根据用户的需求,将应用程序、程序运行的系统函数库、运行配置等文件打包成一个镜像。通过自定义镜像,可以将应用及其运行环境封装在一起,方便在不同的环境中部署和运行。
(二)构建自定义镜像的步骤
以部署 Java 应用为例:
- 准备 Linux 运行环境:可以选择基于
ubuntu
、centos
等基础镜像来构建。 - 安装 JRE 并配置环境变量:在选择的基础镜像中安装 Java 运行时环境(JRE),并配置
JAVA_HOME
等环境变量,确保 Java 应用能够正常运行。 - 拷贝 Jar 包:将开发好的 Java 应用的 Jar 包拷贝到镜像中的指定目录。
- 编写运行脚本:编写一个启动脚本,用于在容器启动时运行 Java 应用,例如
java -jar xx.jar
。
(三)Dockerfile 的使用
- Dockerfile 的概念:Dockerfile 是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。Docker 可以根据 Dockerfile 自动构建镜像。
- 常见指令:
FROM
:指定基础镜像,例如FROM centos:6
以centos:6
为基础镜像构建新镜像。ENV
:设置环境变量,可在后面指令使用,如ENV JAVA_DIR=/usr/local
设置 Java 的安装目录环境变量。COPY
:拷贝本地文件到镜像的指定目录,COPY ./jre11.tar.gz /tmp
将本地的jre11.tar.gz
文件拷贝到镜像的/tmp
目录。RUN
:执行 Linux 的 shell 命令,一般用于安装过程的命令,如RUN tar -zxvf /tmp/jre11.tar.gz && EXPORTS path=/tmp/jre11:$path
解压 JRE 安装包并配置环境变量。EXPOSE
:指定容器运行时监听的端口,是给镜像使用者看的,EXPOSE 8080
表示容器内的应用监听 8080 端口。ENTRYPOINT
:镜像中应用的启动命令,容器运行时调用,ENTRYPOINT java -jar xx.jar
设置 Java 应用的启动命令。
(四)案例 - 构建 Java 镜像
- 基于 Ubuntu 基础镜像构建 Java 镜像:
# 指定基础镜像
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
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
- 基于 JDK 基础镜像构建 Java 镜像(简化步骤):
# 基础镜像
FROM openjdk:11.0-jre-buster
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
- 构建镜像:编写好 Dockerfile 后,在包含 Dockerfile 的目录下执行以下命令构建镜像:
docker build -t myImage:1.0 .
-t
参数给镜像起名,格式为repository:tag
,不指定tag
时默认为latest
;最后的.
表示 Dockerfile 所在目录为当前目录。
七、容器网络
(一)默认网络模式
默认情况下,所有容器都是以bridge
方式连接到 Docker 的一个虚拟网桥上,如docker0
。每个容器在该网络中都有一个独立的 IP 地址,容器之间可以通过 IP 地址进行通信,但无法通过容器名直接访问。例如,容器 A 的 IP 地址是172.17.0.2
,容器 B 的 IP 地址是172.17.0.3
,容器 A 可以通过172.17.0.3
访问容器 B,但不能通过容器 B 的名称访问。
(二)自定义网络
加入自定义网络的容器才可以通过容器名互相访问。使用自定义网络可以更好地管理容器之间的通信和隔离,提高容器网络的灵活性和安全性。
- 创建自定义网络:
docker network create my_network
创建名为my_network
的自定义网络。 - 将容器加入自定义网络:在创建容器时,使用
--network
参数将容器加入自定义网络,例如:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
--network my_network \
mysql
这样,加入my_network
网络的其他容器就可以通过mysql
这个容器名访问该 MySQL 容器。
八、项目部署
(一)部署 Java 应用
- 需求:将课前资料提供的
hmall
项目打包为镜像并部署,镜像名hmall
。 - 步骤:
- 编写
hmall
项目的 Dockerfile,根据项目的依赖和运行要求,选择合适的基础镜像,安装相关依赖,拷贝项目 Jar 包,设置启动命令。例如:
- 编写
FROM openjdk:11.0-jre-buster
COPY hmall.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
- 构建
hmall
镜像:在包含 Dockerfile 的目录下执行docker build -t hmall:1.0 .
。 - 运行
hmall
容器:
docker run -d \
--name hmall \
-p 8080:8080 \
hmall:1.0
上述命令将hmall
镜像运行在容器中,并将容器的 8080 端口映射到宿主机的 8080 端口,外部可通过宿主机的 8080 端口访问hmall
应用。
(二)部署前端
- 需求:创建一个新的 Nginx 容器,将课前资料提供的
nginx.conf
、html
目录与容器挂载。 - 步骤:
- 确保有
nginx.conf
配置文件和html
目录,其中html
目录包含前端页面文件。 - 运行 Nginx 容器并挂载文件:
- 确保有
docker run -d \
--name nginx \
-p 80:80 \
-v /path/to/nginx.conf:/etc/nginx/nginx.conf \
-v /path/to/html:/usr/share/nginx/html \
nginx
将/path/to/nginx.conf
替换为本地nginx.conf
文件的路径,/path/to/html
替换为本地html
目录的路径。这样,Nginx 容器会使用挂载的配置文件和前端页面文件对外提供服务。
(三)使用 Docker Compose 进行多容器部署
- Docker Compose 概述:Docker Compose 通过一个单独的
docker-compose.yml
模板文件(YAML 格式)来定义一组相关联的应用容器,帮助实现多个相互关联的 Docker 容器的快速部署。它可以管理容器的创建、启动、停止、重启等操作,还能处理容器之间的依赖关系、网络配置和数据卷挂载等。 docker-compose.yml
文件示例:
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
version
指定 Compose 文件的版本。services
部分定义各个服务(容器)。mysql
服务使用mysql
镜像,设置端口映射、环境变量、数据卷挂载和网络配置,mysql
服务依赖于hm - net
网络。hmall
服务通过build
指定构建镜像的上下文和 Dockerfile,设置端口映射、网络配置和依赖关系,hmall
依赖于mysql
服务,即会在mysql
启动后再启动。nginx
服务使用nginx
镜像,设置端口映射、数据卷挂载、依赖关系和网络配置,nginx
依赖于hmall
服务。
networks
部分定义自定义网络hm - net
,并设置其别名为hmall
。
- Docker Compose 常用命令:
docker compose up
:创建并启动所有服务容器。如果镜像不存在,会自动拉取或构建。加上-d
参数可在后台运行。docker compose down
:停止并移除所有容器、网络,清理相关资源。docker compose ps
:列出所有启动的容器。docker compose logs
:查看指定容器的日志,例如docker compose logs hmall
查看hmall
容器的日志。docker compose stop
:停止容器。docker compose start
:启动容器。docker compose restart
:重启容器。docker compose top
:查看运行的进程。docker compose exec
:在指定的运行中容器中执行命令,如docker compose exec hmall bash
在hmall
容器中执行bash
命令进入容器内部。
九、总结
(一)Docker 的优势
- 快速部署:通过镜像和容器技术,能快速创建和启动应用,大大缩短部署时间,提高开发和运维效率。
- 环境一致性:确保应用在不同环境(开发、测试、生产)中运行环境一致,减少因环境差异导致的问题。
- 资源隔离:容器之间相互隔离,保证应用的独立性和安全性,同时合理利用系统资源。
- 易于扩展和管理:方便添加、删除和更新容器,通过 Docker Compose 可轻松管理多个相关容器的部署和运维。
(二)学习建议
- 多实践:通过实际操作各种案例,如部署不同类型的应用、使用数据卷和自定义网络等,加深对 Docker 概念和命令的理解。
- 阅读官方文档:官方文档提供了详细的命令说明、最佳实践和技术细节,是深入学习 Docker 的重要资源。
- 参与社区:关注 Docker 社区,参与讨论和交流,获取最新的技术动态和解决方案,与其他开发者共同学习和进步。