Docker入门教程

1. Docker 的基本概念

  1. 镜像(Image)
    • Docker 镜像是运行容器的基础,比如 ubuntunginxmysql 等。
  2. 容器(Container)
    • 运行中的镜像就是容器,容器是一个独立的环境,类似于虚拟机,但比虚拟机更轻量。
  3. 仓库(Registry)
    • 存放 Docker 镜像的地方,比如 Docker Hub(官方公共仓库),你也可以搭建私有仓库。

2. 基本使用

1.运行第一个容器

1
2
# 下载并运行一个测试镜像
docker run hello-world

(可选) 让当前用户无需 sudo 即可使用 Docker:

1
sudo usermod -aG docker $USER

2.常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 拉取镜像(以 Ubuntu 为例)
docker pull ubuntu:20.04

# 查看本地镜像
docker images

# 运行交互式容器
docker run -it ubuntu:20.04 /bin/bash
# (在容器内输入 exit 退出)

# 查看运行中的容器
docker ps

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

# 停止容器
docker stop <容器ID>

# 删除容器
docker rm <容器ID>

# 删除镜像
docker rmi <镜像名>

详解docker run -it ubuntu:20.04 /bin/bash

部分 说明
docker Docker 命令行工具
run 创建并启动一个新容器
-i --interactive 的缩写,保持标准输入流(STDIN)打开,允许与容器交互
-t --tty 的缩写,为容器分配一个伪终端(pseudo-TTY)
ubuntu:20.04 指定使用的镜像名称和标签(这里是 Ubuntu 20.04 版本)
/bin/bash 容器启动后要执行的命令(这里是启动 Bash shell)

3. Docker 数据管理(Volumes & Bind Mounts)

1. 数据卷(Volumes)(推荐方式)

Docker 管理的持久化存储,最适合生产环境。

1. 创建和使用数据卷

1
2
3
4
5
6
7
8
# 创建数据卷
docker volume create my_volume

# 使用数据卷(将数据卷挂载到容器内的 /mydata 目录)
docker run -it -v my_volume:/mydata ubuntu:20.04 /bin/bash

# 查看数据卷详情
docker volume inspect my_volume

特点:

  • 数据存储在 Docker 管理的区域(Linux 默认在 /var/lib/docker/volumes/
  • 即使容器被删除,数据依然保留
  • 支持跨容器共享
  • 适合数据库等需要持久化的场景

2. Bind Mounts(绑定挂载)

Bind Mounts 直接将宿主机的目录挂载到容器,适用于:

  • 开发环境:修改宿主机代码后,容器可立即生效。

  • 访问宿主机文件,如 logs 目录。

    1
    2
    3
    4
    5
    # 挂载主机目录到容器(注意使用绝对路径)
    docker run -it -v /host/path:/container/path ubuntu:20.04 /bin/bash

    # 示例:挂载当前目录到容器的 /mydata
    docker run -it -v $(pwd):/mydata ubuntu:20.04 /bin/bash

3. 临时数据存储(匿名 Volume)

1
2
docker run -it -v /tmpdata ubuntu:20.04 /bin/bash

实例:

1
docker run -d -v my_volume:/app/data --name my_container nginx
部分 说明
docker run 创建并启动一个新容器
-d --detach 的缩写,让容器在后台运行
-v my_volume:/app/data 挂载数据卷(数据卷my_volume 挂载到容器内的 /app/data 路径,如果该数据卷不存在,Docker 会自动创建它)
--name my_container 为容器指定名称(而不是使用随机生成的 ID)
nginx 使用的镜像名称(默认从 Docker Hub 下载最新版 nginx)

4. Docker 网络(Networking)

端口映射

将容器端口暴露给主机:

1
2
3
4
5
6
7
8
# 将容器80端口映射到主机8080端口
docker run -p 8080:80 nginx

# 随机映射
docker run -p 80 nginx

# 指定主机IP
docker run -p 192.168.1.100:8080:80 nginx

5. 小技巧

例子:

1
docker run -d -p 8011:80 -v my_volume:/app/data --name my_container nginx

这条 Docker 命令的作用是在后台运行一个基于 Nginx 镜像的容器,并配置了端口映射、数据卷挂载和容器名称。

以后就可以直接用容器名称对容器进行操作了:

1
2
3
4
5
6
7
8
# 停止容器
docker stop my_container

# 启动已停止的容器
docker start my_container

# 删除容器
docker rm my_container

添加 --rm 参数让容器停止时自动删除(适合临时测试):

1
docker run -d --rm -p 8011:80 -v my_volume:/app/data --name my_container nginx

6. Dockerfile(构建自定义镜像)

一个 Dockerfile 由多条指令组成,常见的指令如下:

指令 作用
FROM 指定基础镜像(如 ubuntualpine
RUN 运行命令(如安装软件)
COPY 复制文件到容器
ADD 复制文件或解压 .tar 文件
WORKDIR 设置工作目录
CMD 容器启动时执行的命令
ENTRYPOINT 指定容器的主进程
EXPOSE 声明容器监听的端口
ENV 设置环境变量

1. 编写一个简单的 Dockerfile

假设你想创建一个基于 Nginx 的自定义镜像,并添加一个 index.html 文件。

1. 创建 index.html

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Docker Nginx</title>
</head>
<body>
<h1>Hello, Docker!</h1>
</body>
</html>

2. 创建 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
# 使用官方 Nginx 作为基础镜像
FROM nginx

# 复制 index.html 到 Nginx 的默认目录
COPY index.html /usr/share/nginx/html/

# 公开 80 端口
EXPOSE 80

# 运行 Nginx
CMD ["nginx", "-g", "daemon off;"]

3. 构建镜像

1
docker build -t my-nginx .
  • -t my-nginx:指定镜像名称 my-nginx
  • .:表示 Dockerfile 在当前目录

4. 运行容器

1
docker run -d -p 8080:80 my-nginx
  • -p 8080:80:将宿主机的 8080 端口映射到容器 80 端口
  • 访问 http://localhost:8080,你会看到 Hello, Docker!

2. 使用 ENTRYPOINTCMD

区别

CMD 提供默认命令,可以被 docker run 覆盖:

1
CMD ["echo", "Hello Docker!"]

ENTRYPOINT 强制执行命令,不会被 docker run 覆盖:

1
ENTRYPOINT ["echo", "Hello Docker!"]

例子:

Dockerfile

1
2
FROM ubuntu
CMD ["echo", "默认 CMD"]

运行:

1
docker build -t my-ubuntu1 .

然后运行:

1
docker run my-ubuntu1

输出:

1
默认 CMD

运行:

1
docker run my-ubuntu1 echo "覆盖 CMD"

输出:

1
覆盖 CMD

例子2:

Dockerfile

1
2
FROM ubuntu
ENTRYPOINT ["echo", "强制执行"]

运行:

1
docker build -t my-ubuntu2 .

然后运行:

1
docker run my-ubuntu2

输出:

1
强制执行

运行:

1
docker run my-ubuntu2 echo "不会覆盖"

输出:

1
强制执行 echo 不会覆盖