Docker介绍与使用:从入门到实际部署
一、前言
在传统的软件开发过程中,经常会遇到这样的问题:
“我的电脑上可以运行,为什么换一台电脑就不能运行了?”
一个应用程序能够正常运行,往往不仅依赖源代码,还依赖特定版本的操作系统、运行环境、第三方库以及各种配置。
例如,一个 Java 项目可能要求:
-
JDK 17;
-
Maven;
-
特定版本的数据库;
-
Redis;
-
Linux 环境;
-
特定的环境变量。
如果开发环境和生产环境存在差异,就可能出现“开发环境正常,部署之后出现问题”的情况。
Docker 正是为了解决这类问题而出现的。
Docker 可以将应用程序以及运行所需要的环境、依赖和配置封装到一个相对独立的容器中,从而提高应用部署的一致性和可移植性。
二、什么是 Docker?
Docker 是一种容器化技术平台。
简单来说,可以把 Docker 理解为:
把应用程序和它运行所需要的环境一起打包,然后放到一个隔离的运行环境中执行。
例如,我们有一个 Java Web 项目:
Java项目
├── 项目代码
├── JDK
├── 第三方依赖
├── 配置文件
└── 运行环境
传统部署方式需要在服务器上分别安装这些环境。
而使用 Docker 后,可以将应用构建成一个镜像:
Docker Image
├── Linux基础环境
├── JDK
├── Java依赖
├── 项目代码
└── 配置
然后利用这个镜像创建容器。
Docker镜像
↓
创建容器
↓
运行应用
这样可以大幅降低环境配置差异带来的问题。
三、Docker中的几个核心概念
学习 Docker 时,最重要的是理解以下几个概念:
-
Image(镜像)
-
Container(容器)
-
Dockerfile
-
Docker Registry
-
Volume(数据卷)
-
Network(网络)
其中最核心的是:
镜像 → 容器
1. Docker Image
Docker Image,也就是 Docker 镜像。
镜像可以理解为一个用于创建容器的模板。
例如:
nginx镜像
↓
创建Nginx容器
↓
运行Nginx
一个镜像通常包含:
-
基础操作系统环境;
-
应用程序;
-
运行时环境;
-
依赖库;
-
配置文件;
-
启动命令。
常见镜像包括:
nginx
mysql
redis
ubuntu
alpine
node
python
openjdk
四、什么是容器?
Container,也就是容器。
容器是镜像运行后的实例。
可以用一个比较简单的比喻理解:
镜像 = 程序安装包/模板
容器 = 根据模板运行起来的实例
例如:
nginx镜像
│
├── 容器A
│
├── 容器B
│
└── 容器C
多个容器可以由同一个镜像创建。
而且不同容器之间通常具有相对独立的文件系统、网络和进程环境。
五、Docker与虚拟机有什么区别?
很多初学者容易把 Docker 和虚拟机混淆。
传统虚拟机通常是:
物理服务器
↓
虚拟机管理程序
↓
虚拟机
↓
完整操作系统
↓
应用程序
Docker 容器则更接近:
物理服务器
↓
操作系统
↓
Docker Engine
↓
容器
↓
应用程序
Docker 容器共享宿主机的 Linux 内核,而虚拟机通常需要运行完整的 Guest OS。
因此,在很多应用场景下,容器启动速度和资源利用效率都比较有优势。
不过,Docker 并不是虚拟机的完全替代品。两者解决的问题存在重叠,也各有适合的使用场景。
六、安装 Docker
Docker 的安装方式与操作系统有关。
对于 Linux 系统,可以根据发行版使用 Docker 官方提供的安装方式。
安装完成后,可以执行:
docker --version
如果安装成功,可以看到类似:
Docker version ...
然后可以运行:
docker info
查看 Docker Engine 的详细信息。
七、运行第一个 Docker 容器
安装 Docker 后,可以尝试运行一个 Nginx 容器。
docker run -d -p 8080:80 nginx
这条命令虽然很短,但包含了几个重要概念。
其中:
docker run
表示创建并运行一个容器。
-d
表示后台运行。
-p 8080:80
表示端口映射:
宿主机8080端口
↓
容器80端口
最后的:
nginx
表示使用 Nginx 镜像。
运行完成后,可以访问:
http://localhost:8080
如果看到 Nginx 的欢迎页面,就说明第一个 Docker 容器已经成功运行。
八、查看正在运行的容器
使用:
docker ps
可以查看当前正在运行的容器。
例如:
CONTAINER ID IMAGE COMMAND STATUS PORTS
xxxxxxxxxxxx nginx ... Up 0.0.0.0:8080->80/tcp
如果希望查看所有容器,包括已经停止的容器,可以使用:
docker ps -a
九、停止和启动容器
首先通过:
docker ps
找到容器 ID。
然后停止容器:
docker stop 容器ID
例如:
docker stop abc123
重新启动:
docker start abc123
如果不再需要这个容器,可以删除:
docker rm abc123
十、查看 Docker 镜像
可以使用:
docker images
查看本地已有镜像。
例如:
REPOSITORY TAG IMAGE ID CREATED
nginx latest xxxxxxxxxxxx ...
ubuntu latest xxxxxxxxxxxx ...
删除镜像:
docker rmi 镜像ID
需要注意,如果某个镜像仍然被容器使用,直接删除可能会失败。
十一、Docker Hub 与镜像仓库
Docker 镜像通常来自镜像仓库。
最常见的公共镜像仓库之一是 Docker Hub。
例如:
nginx
mysql
redis
ubuntu
python
node
当执行:
docker pull nginx
Docker 会尝试从配置的镜像仓库获取 Nginx 镜像。
执行:
docker pull redis
则可以获取 Redis 镜像。
镜像仓库的作用可以简单理解为:
开发者
↓
构建Docker镜像
↓
上传镜像仓库
↓
服务器拉取镜像
↓
创建容器
在企业环境中,也经常使用私有镜像仓库来保存企业内部的镜像。
十二、Dockerfile:自己构建镜像
实际开发中,我们不可能永远只使用别人提供的镜像。
如果需要把自己的程序打包成 Docker 镜像,就需要使用 Dockerfile。
Dockerfile 是 Docker 镜像的构建描述文件。
例如:
FROM nginx:latest
COPY ./html /usr/share/nginx/html
这里:
FROM nginx:latest
表示使用 Nginx 作为基础镜像。
而:
COPY ./html /usr/share/nginx/html
表示将当前目录中的 html 文件夹复制到 Nginx 的网站目录。
项目结构可以是:
my-nginx/
├── Dockerfile
└── html/
└── index.html
十三、构建自己的 Docker 镜像
进入项目目录:
cd my-nginx
执行:
docker build -t my-nginx:1.0 .
其中:
docker build
表示构建镜像。
-t my-nginx:1.0
表示给镜像设置名称和版本标签。
最后的:
.
表示使用当前目录作为构建上下文。
构建完成后:
docker images
应该可以看到:
my-nginx 1.0
然后运行:
docker run -d -p 8080:80 my-nginx:1.0
这样就可以运行自己构建的镜像。
十四、Dockerfile的基本指令
Dockerfile 中有很多指令,其中比较常用的包括:
FROM
指定基础镜像。
FROM ubuntu:24.04
RUN
在构建镜像时执行命令。
RUN apt update
COPY
复制文件。
COPY app.jar /app/app.jar
WORKDIR
设置工作目录。
WORKDIR /app
ENV
设置环境变量。
ENV APP_ENV=production
EXPOSE
声明容器使用的端口。
EXPOSE 8080
CMD
指定容器启动时执行的默认命令。
例如:
CMD ["java", "-jar", "app.jar"]
这些指令组合起来,就可以描述一个应用的 Docker 镜像应该如何构建和运行。
十五、数据卷 Volume
Docker 容器有一个非常重要的问题:
如果容器删除了,里面的数据怎么办?
例如数据库容器中保存了大量数据。
如果数据直接存储在容器内部,删除容器后可能导致数据丢失。
因此 Docker 提供了 Volume,也就是数据卷。
例如:
docker volume create mysql-data
然后运行 MySQL:
docker run -d \
--name mysql \
-v mysql-data:/var/lib/mysql \
mysql
这里:
mysql-data
是 Docker Volume。
而:
/var/lib/mysql
是容器中的数据库数据目录。
这样即使删除 MySQL 容器,只要 Volume 仍然存在,就可以在新的容器中继续使用这些数据。
十六、Docker网络
多个容器之间往往需要互相通信。
例如一个典型的网站系统:
Nginx
↓
后端应用
↓
MySQL
↓
Redis
Docker 可以通过 Network 为这些容器提供网络通信。
创建网络:
docker network create my-network
运行容器时加入网络:
docker run -d \
--name mysql \
--network my-network \
mysql
另一个应用容器也加入:
docker run -d \
--name app \
--network my-network \
my-app
在同一个 Docker 网络中,应用通常可以通过容器名称进行服务发现。
例如:
app → mysql
应用配置中的数据库地址可以使用:
mysql
而不是写死某个 IP 地址。
十七、Docker Compose
当项目中存在多个容器时,如果每一个容器都手动执行 docker run,管理起来会比较麻烦。
例如一个 Web 项目可能需要:
Nginx
MySQL
Redis
后端应用
这时候可以使用 Docker Compose。
Docker Compose 可以通过一个 YAML 文件描述整个应用所需要的服务。
例如:
services:
nginx:
image: nginx:latest
ports:
- "8080:80"
redis:
image: redis:latest
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: example
然后可以通过:
docker compose up -d
一次启动多个服务。
停止:
docker compose down
查看服务:
docker compose ps
查看日志:
docker compose logs
这也是 Docker 在实际开发中非常重要的使用方式。
十八、一个典型的 Docker 项目结构
实际项目中,可以采用类似的目录结构:
my-project/
├── Dockerfile
├── compose.yaml
├── .dockerignore
├── src/
├── config/
└── README.md
其中:
Dockerfile
负责构建应用镜像。
compose.yaml
负责描述多个服务。
.dockerignore
用于排除不需要复制到构建上下文中的文件。
例如:
.git
node_modules
target
*.log
.env
这样可以减少 Docker 构建上下文的大小。
十九、Docker常用命令总结
日常使用 Docker 时,经常会用到以下命令:
| 命令 | 作用 |
|---|---|
docker --version |
查看 Docker 版本 |
docker ps |
查看运行中的容器 |
docker ps -a |
查看所有容器 |
docker images |
查看镜像 |
docker pull |
下载镜像 |
docker build |
构建镜像 |
docker run |
创建并运行容器 |
docker start |
启动容器 |
docker stop |
停止容器 |
docker restart |
重启容器 |
docker rm |
删除容器 |
docker rmi |
删除镜像 |
docker logs |
查看容器日志 |
docker exec |
进入正在运行的容器执行命令 |
docker inspect |
查看容器或镜像详细信息 |
docker volume ls |
查看数据卷 |
docker network ls |
查看 Docker 网络 |
docker compose up |
启动 Compose 服务 |
docker compose down |
停止并删除 Compose 服务 |
二十、Docker使用中的常见问题
1. 容器启动后马上退出
可以使用:
docker ps -a
查看容器状态。
然后:
docker logs 容器名称
查看程序输出。
很多情况下,容器退出并不是 Docker 出错,而是容器中的主进程执行结束了。
2. 宿主机无法访问容器服务
需要检查:
容器是否运行
↓
容器端口是否监听
↓
是否进行了端口映射
↓
宿主机防火墙
↓
云服务器安全组
例如容器监听 80 端口:
容器:80
如果希望宿主机通过 8080 访问,就需要:
docker run -p 8080:80 nginx
3. 容器中的数据消失
如果没有使用 Volume,数据可能随着容器删除而丢失。
因此数据库等有状态服务应该重点考虑:
-
Volume;
-
数据库备份;
-
快照;
-
异地备份。
二十一、Docker的优势
Docker 的主要优势包括:
环境一致性
开发、测试和生产环境可以使用相同的镜像。
部署方便
通过镜像可以快速创建应用环境。
隔离性
不同应用可以运行在不同容器中,减少环境冲突。
可移植性
只要目标环境支持 Docker,就可以运行相同或兼容的容器镜像。
资源利用率较高
相比运行多个完整虚拟机,容器通常具有更低的资源开销。
方便持续集成和持续部署
Docker 镜像可以很好地与 CI/CD 流程结合,实现自动构建、测试和部署。
二十二、Docker并不是万能的
虽然 Docker 有很多优势,但也不能认为所有应用都应该使用 Docker。
例如:
-
对硬件有特殊要求的程序;
-
对隔离级别要求极高的场景;
-
某些复杂的有状态系统;
-
对容器技术没有适配的旧系统。
在实际项目中,需要根据业务需求选择合适的部署方式。
同时,使用 Docker 后也需要关注:
-
镜像安全;
-
容器权限;
-
网络安全;
-
密钥管理;
-
数据备份;
-
镜像漏洞;
-
日志管理。
Docker 解决的是应用打包和运行环境一致性等问题,并不能自动解决所有运维和安全问题。
二十三、总结
Docker 的核心思想可以概括为:
应用程序
+
运行环境
+
依赖
↓
Docker镜像
↓
Docker容器
↓
运行应用
学习 Docker 时,不需要一开始就掌握所有高级功能。
建议按照以下路线学习:
Docker基础概念
↓
镜像
↓
容器
↓
Dockerfile
↓
Volume
↓
Network
↓
Docker Compose
↓
项目容器化
↓
CI/CD
↓
容器集群与云原生
对于初学者来说,最好的学习方式不是只记命令,而是亲自完成一个完整的小项目。
例如,可以尝试部署:
Nginx
↓
Java / Node.js / Python后端
↓
MySQL
↓
Redis
然后使用 Docker Compose 将整个项目统一管理。
当能够独立完成从编写代码 → 构建镜像 → 创建容器 → 配置网络 → 持久化数据 → 查看日志 → 部署应用这一整套流程后,Docker 的核心使用方法基本就掌握了。
Docker 也可以作为进一步学习 Kubernetes、CI/CD 和云原生技术的重要基础。
- 点赞
- 收藏
- 关注作者
评论(0)