Docker零基础入门指南
第一部分:Docker 核心概念 - 它是什么?为什么需要它?
在学习具体命令之前,理解其背后的思想至关重要。
1. 问题背景:“在我这运行得好好的!”
软件开发中最大的痛点之一就是环境问题。开发、测试、生产环境的不一致(操作系统、依赖库、配置等)会导致应用行为异常,部署困难。
2. Docker 的解决方案:容器化
Docker 将一个应用程序及其所有依赖项(代码、运行时、系统工具、系统库、设置)打包成一个标准化的单元,这个单元就称为容器(Container)。这个容器可以在任何安装了 Docker 的环境中一致地运行。
3. 核心概念拆解
-
镜像(Image):
-
比喻:镜像是容器的“蓝图”或“安装包”。它是一个只读的模板,包含了创建容器所需的所有文件和指令。例如,一个 Ubuntu 镜像、一个带有 Python 和 Flask 的 Web 应用镜像。
-
特点:镜像是分层的,每一层代表镜像构建过程中的一条指令。这种分层结构使得镜像非常轻量、易于共享和存储。
-
-
容器(Container):
-
比喻:容器是从镜像创建并运行起来的一个实例。就像你根据蓝图(镜像)建造了一栋可以住人的房子(容器)。你可以同时运行多个基于同一镜像的容器(多个房子),它们相互隔离。
-
特点:容器是可写的。在容器运行时,会在镜像层之上创建一个新的可写层(容器层),所有对容器的修改都发生在这里。容器停止后,这个可写层默认也会被删除(数据会丢失,除非使用卷)。
-
-
仓库(Registry):
-
比喻:类似于 GitHub,是存放镜像的地方。
-
Docker Hub:最大的公共仓库,官方和社区提供了大量高质量的基础镜像(如
nginx
,redis
,python
,node
)。 -
你也可以搭建私有仓库(如 Harbor)来存储公司内部的镜像。
-
-
Dockerfile:
-
一个纯文本文件,里面包含了一系列的指令(Instruction),用于指导 Docker 如何自动构建一个镜像。
-
例如:
FROM
指定基础镜像,RUN
执行命令,COPY
复制文件,CMD
指定容器启动命令。
-
第二部分:安装与配置
-
配置安装仓库
# 安装必要的依赖包 sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg lsb-release # 添加Docker的GPG密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 设置Docker的阿里云源 echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
-
下载安装docker
# 更新包索引并安装Docker组件 sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 验证安装是否成功 docker --version # 查看Docker版本 docker compose version # 查看Docker Compose版本 docker info # 查看Docker的详细信息
-
由于国内经常无法访问docker仓库,我们来配置几个docker镜像加速器:
# 创建Docker配置目录 mkdir -p /etc/docker # 写入加速配置 tee /etc/docker/daemon.json <<EOF {"registry-mirrors": ["https://docker.1ms.run","https://docker.xuanyuan.me"] } EOF # 重启Docker使配置生效 systemctl daemon-reload systemctl restart docker
我们也可以配置属于自己docker仓库,具体可以参考我的另一篇博客。搭建专属Docker镜像仓库:Harbor私有仓库全攻略_harbor镜像仓库-CSDN博客
第三部分:日常开发中最常用的 Docker 命令
1. 镜像相关命令
-
拉取镜像(从仓库下载到本地):
docker pull [镜像名]:[标签] # 示例:拉取官方的 Ubuntu 20.04 镜像 docker pull ubuntu:20.04 # 如果不指定标签,默认拉取 latest 标签 docker pull nginx
-
查看本地镜像:
docker images # 或 docker image ls
-
删除镜像:
docker rmi [镜像ID或镜像名] # 示例:强制删除一个镜像 # 注意:删除镜像前必须先停止并删除基于该镜像运行的容器 docker rmi -f ubuntu:20.04
-
构建镜像(通过 Dockerfile):
# 在当前目录(包含Dockerfile)构建镜像,并命名为 my-app docker build -t my-app:1.0 . # -t:给镜像打标签 # . :构建上下文路径
2. 容器相关命令
-
运行容器(最核心的命令):
docker run [选项] [镜像名] [命令]
常用选项:
-
-d
:后台运行(守护模式) -
-it
:交互模式运行(通常与-d
二选一),-i
保持标准输入打开,-t
分配一个伪终端,合起来可以进入容器内部。 -
--name
:给容器起一个名字(否则 Docker 会随机分配) -
-p
:端口映射,主机端口:容器端口
-
-v
:数据卷映射,主机目录:容器目录
,用于数据持久化 -
-e
:设置环境变量 -
--rm
:容器停止后自动删除
示例:
-
交互式运行一个Ubuntu容器,并进入它的bash shell
docker run -it --name my-ubuntu ubuntu:20.04 /bin/bash
-
后台运行一个Nginx容器,并将主机的8080端口映射到容器的80端口
docker run -d --name my-nginx -p 8080:80 nginx # 现在可以在浏览器访问 http://[主机IP]:8080
-
-
查看容器:
# 查看正在运行的容器 docker ps # 查看所有容器(包括已停止的) docker ps -a
-
停止/启动/重启容器:
docker stop [容器名或ID] docker start [容器名或ID] # 启动已停止的容器 docker restart [容器名或ID]
-
进入正在运行的容器:
# 进入一个后台运行的容器,并启动一个bash shell docker exec -it [容器名或ID] /bin/bash # 示例:进入my-nginx容器 docker exec -it my-nginx /bin/bash
注意:
docker run -it
是创建新容器并进入,docker exec -it
是进入已运行的容器。 -
查看容器日志:
docker logs [容器名或ID] # -f 实时跟踪日志输出(类似 tail -f) docker logs -f my-nginx # --tail 显示末尾行数 docker logs --tail 10 my-nginx
-
删除容器:
docker rm [容器名或ID] # 强制删除一个正在运行的容器(谨慎使用) docker rm -f my-nginx # 删除所有已停止的容器 docker container prune
-
查看容器资源使用情况:
docker stats my-nginx
第四部分:实战 - 从 Dockerfile 到运行应用
假设我们有一个简单的 Python Flask 应用。
-
项目结构:
my_flask_app/ ├── app.py ├── requirements.txt └── Dockerfile
-
app.py:
from flask import Flask app = Flask(__name__) @app.route('/') def hello():return "Hello, Docker World!" if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)
-
requirements.txt:
Flask==2.3.3
-
Dockerfile:
# 使用官方Python运行时作为父镜像 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 将当前目录内容复制到容器的 /app 下 COPY . . # 安装requirements.txt中指定的任何需要的包 RUN pip install --no-cache-dir -r requirements.txt # 让容器监听5000端口 EXPOSE 5000 # 定义环境变量 ENV FLASK_APP=app.py # 容器启动时运行 app.py CMD ["flask", "run", "--host=0.0.0.0"]
-
构建和运行:
# 1. 构建镜像 cd my_flask_app docker build -t my-flask-app:1.0 . # 2. 运行容器 docker run -d -p 5000:5000 --name my-running-app my-flask-app # 3. 访问应用 # 打开浏览器访问 http://[主机IP]:5000
打开浏览器访问 http://[主机IP]:8000
第五部分:进阶概念与最佳实践
-
数据持久化:卷(Volume)和绑定挂载(Bind Mount)
-
容器的可写层是临时的,容器删除数据就没了。
-
卷(Volume):由 Docker 管理的持久化数据存储方式,与容器生命周期解耦。是最佳实践。
docker volume create my-vol # 创建卷 docker run -d -v my-vol:/app/data my-app # 使用卷
-
绑定挂载(Bind Mount):将主机上的一个特定目录或文件挂载到容器中。常用于开发时同步代码。
# 开发时使用,修改主机代码,容器内实时生效 docker run -d -v $(pwd):/app -p 5000:5000 my-flask-app
-
-
网络(Network)
-
默认情况下,所有容器都连接在默认的
bridge
网络上,可以通过 IP 地址通信。 -
可以创建自定义网络,容器加入同一网络后,可以通过容器名互相访问(Docker 内置 DNS)。
docker network create my-net docker run -d --name web --network my-net nginx
-
-
Docker Compose:管理多容器应用
-
现实的应用通常由多个容器组成(如 Web 应用 + 数据库 + 缓存)。
-
Docker Compose 允许你用一个
YAML
文件(docker-compose.yml
)来定义和运行多个容器。 -
示例
docker-compose.yml
(运行 WordPress):version: '3.8' services:db:image: mysql:8.0volumes:- db_data:/var/lib/mysqlenvironment:MYSQL_ROOT_PASSWORD: somewordpressMYSQL_DATABASE: wordpressMYSQL_USER: wordpressMYSQL_PASSWORD: wordpress wordpress:image: wordpress:latestports:- "8000:80"environment:WORDPRESS_DB_HOST: dbWORDPRESS_DB_USER: wordpressWORDPRESS_DB_PASSWORD: wordpressWORDPRESS_DB_NAME: wordpressvolumes:- wp_data:/var/www/htmldepends_on:- db volumes:db_data: {}wp_data: {}
-
命令:
# 启动所有服务 docker compose up -d # 停止并删除所有容器、网络 docker compose down # 同时删除数据 docker compose down -v # 查看服务状态 docker compose ps
打开浏览器访问 http://[主机IP]:8000
-
Docker 的生态非常庞大,但掌握了以上核心内容,你就已经具备了解决绝大多数常见问题的能力,可以开始享受容器化带来的高效和便利了。