Docker入门:从安装到第一个容器

容器化是近几年后端开发的必修课。Docker 让你把应用和它的依赖打包到一个轻量级容器中,在任何环境都能一致地运行。这篇文章从零开始,带你跑起第一个 Docker 容器。

核心概念

在动手之前,先理清三个核心概念:

镜像(Image):一个只读的模板,包含运行应用所需的一切——代码、运行时、系统库、配置文件。可以类比为一个"安装包"或者虚拟机的快照。

容器(Container):镜像的运行实例。镜像是静态的,容器是动态的。一个镜像可以创建多个容器,每个容器相互隔离。类比:镜像是类,容器是对象。

仓库(Registry):存放镜像的地方。Docker Hub 是官方的公共仓库,类似于 Maven 仓库或 npm registry。企业通常会搭建私有仓库(如 Harbor)。

安装 Docker

Ubuntu

# 卸载旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc

# 安装依赖
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release

# 添加 Docker 官方 GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 添加 Docker apt 仓库
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# 将当前用户加入 docker 组(免 sudo)
sudo usermod -aG docker $USER

CentOS

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker

安装完成后验证:

docker version
docker run hello-world

如果看到 "Hello from Docker!" 的输出,说明安装成功。

常用命令

镜像管理

# 从 Docker Hub 拉取镜像
docker pull nginx
docker pull python:3.9

# 查看本地镜像列表
docker images

# 删除镜像
docker rmi nginx

# 搜索镜像
docker search redis

容器生命周期

# 运行容器(前台)
docker run nginx

# 运行容器(后台 + 端口映射 + 命名)
docker run -d --name my-nginx -p 8080:80 nginx

# 查看运行中的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

# 停止容器
docker stop my-nginx

# 启动已停止的容器
docker start my-nginx

# 重启容器
docker restart my-nginx

# 删除容器(需先停止)
docker rm my-nginx

# 强制删除运行中的容器
docker rm -f my-nginx

docker run-d 表示后台运行,-p 8080:80 表示将宿主机的 8080 端口映射到容器的 80 端口。运行上面的命令后,访问 http://localhost:8080 就能看到 Nginx 的欢迎页面。

进入容器

# 在运行中的容器里执行命令
docker exec -it my-nginx bash

# 查看容器日志
docker logs my-nginx

# 实时追踪日志
docker logs -f my-nginx

# 查看容器资源使用情况
docker stats

-it-i(交互式)和 -t(分配伪终端)的组合,可以让你像 SSH 一样进入容器内部操作。

数据卷

容器中的数据默认随容器删除而丢失。数据卷可以将宿主机的目录挂载到容器中,实现数据持久化:

# 将宿主机的 /data/nginx 挂载到容器的 /usr/share/nginx/html
docker run -d --name web -p 8080:80 -v /data/nginx:/usr/share/nginx/html nginx

此时修改 /data/nginx 中的文件,容器中的 Nginx 会立即使用新内容。

Dockerfile 基础

Dockerfile 是一个文本文件,定义了如何构建镜像。以一个简单的 Python Web 应用为例:

# 基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 先复制依赖文件并安装(利用缓存层)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 5000

# 启动命令
CMD ["python", "app.py"]

构建和运行:

# 在 Dockerfile 所在目录执行
docker build -t my-flask-app .

# 运行
docker run -d --name flask-web -p 5000:5000 my-flask-app

几个注意点:

  • COPY requirements.txt .RUN pip install 放在 COPY . . 之前,是为了利用 Docker 的层缓存机制。只要 requirements.txt 没变,这两层就会命中缓存,不需要重新安装依赖。
  • --no-cache-dir 避免在镜像中留下 pip 缓存,减小镜像体积。
  • CMDENTRYPOINT 的区别:CMD 可以被 docker run 后面的命令覆盖,ENTRYPOINT 不会。

一个完整的例子

用 Docker 跑一个 Redis 服务,实际体验从拉取到使用的完整流程:

# 拉取 Redis 镜像
docker pull redis:6

# 启动 Redis 容器
docker run -d --name my-redis -p 6379:6379 redis:6

# 进入容器使用 redis-cli
docker exec -it my-redis redis-cli

# 在 redis-cli 中测试
127.0.0.1:6379> SET hello world
OK
127.0.0.1:6379> GET hello
"world"
127.0.0.1:6379> exit

# 查看容器日志
docker logs my-redis

# 用完后清理
docker stop my-redis && docker rm my-redis

整个过程不需要在宿主机上安装 Redis,也不需要操心依赖和配置——这就是 Docker 的魅力。

小结

掌握了镜像、容器、数据卷、Dockerfile 这几个核心概念,就能在日常开发中用好 Docker。后续可以继续学习 Docker Compose(编排多个容器)和 Docker 网络(容器间通信),逐步过渡到 Kubernetes。