Docker 与容器基础学习笔记
什么是容器?
容器(Container)是一种轻量级的软件运行环境,可以把应用程序及其运行所需要的环境、依赖、配置等封装在一起,使应用能够在不同的服务器环境中保持相对一致的运行方式。
传统部署经常会遇到:
开发环境可以运行
↓
换一台服务器
↓
软件版本不同
依赖库不同
配置不同
环境不同
↓
程序运行失败
容器的主要目的就是解决这类"环境不一致"的问题。
可以简单理解为:
容器 = 一个被隔离的应用运行环境。
例如一个 nginx 容器中会包含 nginx 程序以及运行所需要的相关文件。
容器和虚拟机的区别
容器和虚拟机都可以实现环境隔离,但是原理不同。
虚拟机
虚拟机通过 Hypervisor 创建完整的虚拟计算机。
结构:
物理服务器
↓
VMware / KVM
↓
虚拟机
↓
完整操作系统
↓
应用程序
每台虚拟机通常都有独立的:
-
操作系统
-
内核
-
文件系统
-
进程
-
网络环境
因此虚拟机比较重,启动时间通常也更长。
容器
容器不会为每个容器运行一个完整的 Linux 内核,而是共享宿主机的 Linux 内核。
结构:
物理服务器
↓
Linux 内核
↓
Docker
↓
┌─────────┬─────────┬─────────┐
│ nginx │ mysql │ redis │
│ 容器 │ 容器 │ 容器 │
└─────────┴─────────┴─────────┘
因此容器相比虚拟机:
-
启动速度更快
-
占用资源更少
-
部署更加方便
-
更适合微服务和持续交付
容器为什么能够实现隔离?
Linux 本身提供了容器所需要的很多基础能力,Docker 在这些能力之上实现容器运行。
其中最重要的是:
Namespace
Cgroups
分层文件系统
Namespace
Namespace 用来实现资源隔离。
例如宿主机执行:
ps aux
可以看到大量进程。
但是进入容器后:
docker exec -it nginx bash
ps
容器内部看到的进程数量会明显不同。
这是因为容器拥有独立的进程视图。
可以简单理解为:
宿主机:
进程1
进程2
进程3
进程4
进程5
...
↓ Namespace隔离
容器:
进程1
进程2
常见 Namespace 类型包括:
-
PID Namespace:进程隔离
-
NET Namespace:网络隔离
-
MNT Namespace:文件系统挂载隔离
-
UTS Namespace:主机名隔离
-
IPC Namespace:进程间通信隔离
-
User Namespace:用户和权限隔离
Cgroups
Cgroups(Control Groups)主要负责:
控制和限制容器能够使用的系统资源。
例如一台服务器:
CPU:8核
内存:16GB
可以限制某个容器:
CPU:最多使用1核
内存:最多使用512MB
例如:
docker run -d \
--name nginx \
--cpus=1 \
--memory=512m \
nginx
这样可以避免某个容器占用过多资源,影响其他服务。
容器文件系统
容器看起来像一个独立的 Linux 文件系统:
/bin
/etc
/home
/usr
/var
但是它并不是一台真正的虚拟机。
Docker 使用分层文件系统来构建镜像和容器。
一个镜像通常由多个 Layer 组成:
Layer 1
Layer 2
Layer 3
Layer 4
Layer 5
不同镜像可以共享相同的基础 Layer。
例如:
Ubuntu基础层
│
┌──────────┼──────────┐
↓ ↓ ↓
nginx MySQL Redis
这样可以减少存储空间,并提高镜像分发效率。
Docker 是什么?
Docker 是一个用于:
构建、运行、管理和分发容器的平台。
Docker 可以完成:
构建镜像
↓
保存镜像
↓
上传镜像
↓
下载镜像
↓
创建容器
↓
运行容器
↓
管理容器
需要注意:
容器 ≠ Docker
容器是一种技术和运行方式。
Docker 是实现和管理容器的一套平台。
Docker 最重要的三个概念
学习 Docker 时,最重要的是理解:
Image
Container
Registry
即:
镜像
容器
镜像仓库
三者关系:
镜像 Image
↓ docker run
容器 Container
而镜像通常保存在:
Registry
中。
什么是 Docker Image(镜像)?
镜像可以理解为:
创建容器的模板。
例如:
nginx:latest
ubuntu:latest
redis:latest
mysql:latest
镜像里面包含应用程序运行所需要的文件和相关配置。
例如 nginx 镜像可以理解为:
nginx镜像
├── nginx程序
├── 配置文件
├── 依赖文件
└── 基础文件系统
查看本地镜像:
docker images
什么是 Container(容器)?
容器是:
镜像运行之后产生的实例。
关系:
镜像
↓ docker run
容器
例如:
docker run nginx
Docker 会根据 nginx 镜像创建一个 nginx 容器,并启动 nginx 服务。
同一个镜像可以创建多个容器:
nginx镜像
┌─────┼─────┐
↓ ↓ ↓
容器1 容器2 容器3
什么是 Registry(镜像仓库)?
Registry 用于存放 Docker 镜像。
常见 Registry:
Docker Hub
Harbor
Docker Registry
Docker Hub 是公共镜像仓库。
Harbor 是企业中常见的私有镜像仓库。
例如:
Docker Hub
│
├── nginx
├── redis
├── mysql
└── ubuntu
企业内部则可以搭建:
Harbor
reg.example.com
│
├── library/nginx
├── project1/web
└── project2/mysql
Docker 镜像名称
例如:
reg.westos.org/library/nginx:latest
可以拆成:
reg.westos.org
↓
镜像仓库地址
library
↓
项目名称
nginx
↓
镜像名称
latest
↓
标签 Tag
完整结构:
Registry / Project / Image : Tag
docker pull
docker pull 用来从镜像仓库下载镜像。
例如:
docker pull nginx
默认情况下:
nginx
相当于:
docker.io/library/nginx:latest
即默认从 Docker Hub 的 library 项目获取 nginx。
如果指定 Harbor:
docker pull reg.westos.org/library/nginx:latest
则表示从:
reg.westos.org
这个 Harbor 的:
library
项目中获取:
nginx:latest
docker run
docker run 用于根据镜像创建并运行容器。
例如:
docker run nginx
后台运行:
docker run -d nginx
指定容器名称:
docker run -d --name web nginx
完整例子:
docker run -d \
--name web \
-p 8080:80 \
nginx
含义:
-d
后台运行
--name web
容器名称为web
-p 8080:80
宿主机8080端口映射到容器80端口
nginx
使用nginx镜像
为什么容器会停止?
容器本质上是一个被隔离的进程环境。
如果容器中的主进程结束:
主进程退出
↓
容器停止
例如:
docker run ubuntu
可能启动后很快退出。
而 nginx:
docker run -d nginx
由于 nginx 是一个持续运行的服务,因此容器可以持续运行。
docker ps
查看正在运行的容器:
docker ps
查看所有容器:
docker ps -a
例如:
CONTAINER ID
IMAGE
COMMAND
STATUS
PORTS
NAMES
进入容器
可以使用:
docker exec -it 容器名 bash
例如:
docker exec -it web bash
进入以后可以执行:
ls
ps
cat /etc/os-release
退出:
exit
exit 只是退出容器终端,不会停止容器。
Docker 网络
Docker 默认会创建一个:
docker0
网桥。
例如:
宿主机
192.168.150.184
│
docker0
172.17.0.1
│
┌─────┴─────┐
↓ ↓
nginx redis
172.17.0.2 172.17.0.3
容器通常拥有自己的网络空间和 IP 地址。
端口映射
容器内部的服务通常不能直接通过宿主机端口访问。
可以使用 -p 进行端口映射。
例如:
docker run -d -p 8080:80 nginx
表示:
宿主机8080
↓
容器80
↓
nginx
因此浏览器访问:
http://服务器IP:8080
最终访问的是容器中的:
80端口
Docker 数据存储
容器本身具有临时性。
如果重要数据直接放在容器内部,删除容器后可能导致数据丢失。
因此 Docker 提供 Volume。
创建 Volume:
docker volume create mysql-data
使用:
docker run -d \
-v mysql-data:/var/lib/mysql \
mysql
结构:
Docker Volume
↓
容器
↓
/var/lib/mysql
即使删除容器:
docker rm mysql
Volume 中的数据仍然可以保留。
Dockerfile
Dockerfile 是:
构建 Docker 镜像的配置文件。
例如:
FROM nginx:latest
COPY index.html /usr/share/nginx/html/
EXPOSE 80
含义:
FROM
指定基础镜像
COPY
复制文件到镜像
EXPOSE
声明应用使用的端口
构建镜像:
docker build -t mynginx:1.0 .
查看:
docker images
运行:
docker run -d -p 8080:80 mynginx:1.0
Docker 镜像完整生命周期
Docker 的核心工作流程可以总结为:
Dockerfile
↓
docker build
↓
Image
↓
┌───────┴───────┐
↓ ↓
docker run docker push
↓ ↓
Container Registry
│
┌──────┴──────┐
↓ ↓
Docker Hub Harbor
│
↓
docker pull
↓
Container
企业实际部署流程
实际企业中,一个应用从开发到上线通常可以理解为:
开发代码
↓
编写 Dockerfile
↓
docker build
↓
生成 Image
↓
docker tag
↓
docker push
↓
Harbor
↓
生产服务器 docker pull
↓
docker run / docker compose
↓
Container
↓
应用上线
如果使用 CI/CD,还可以进一步自动化:
Git
↓
CI/CD
↓
Docker Build
↓
镜像
↓
Harbor
↓
服务器
↓
Docker Compose / Kubernetes
↓
应用运行
常用 Docker 命令总结
镜像相关
docker images
查看镜像。
docker pull nginx
下载镜像。
docker rmi nginx
删除镜像。
docker tag nginx:latest myrepo/nginx:latest
给镜像重新打标签。
docker build -t myapp:1.0 .
构建镜像。
docker push myrepo/nginx:latest
上传镜像。
容器相关
docker run nginx
创建并运行容器。
docker run -d nginx
后台运行。
docker ps
查看运行中的容器。
docker ps -a
查看所有容器。
docker stop nginx
停止容器。
docker start nginx
启动已有容器。
docker restart nginx
重启容器。
docker rm nginx
删除容器。
docker exec -it nginx bash
进入容器。
docker logs nginx
查看容器日志。
网络相关
docker network ls
查看 Docker 网络。
docker port nginx
查看容器端口映射。
docker run -d -p 8080:80 nginx
进行端口映射。
Volume
docker volume ls
查看 Volume。
docker volume create data
创建 Volume。
docker volume inspect data
查看 Volume 信息。
Compose
docker compose up -d
启动所有服务。
docker compose ps
查看服务状态。
docker compose images
查看服务使用的镜像。
docker compose logs
查看日志。
docker compose down
停止并删除 Compose 创建的容器。
最终理解
学习 Docker 时,可以始终记住下面这条主线:
Dockerfile
↓
docker build
↓
Image(镜像)
↓
Registry(仓库)
↓
docker pull
↓
docker run
↓
Container(容器)
↓
Application(应用)
而在企业环境中:
开发
↓
构建镜像
↓
Harbor
↓
服务器
↓
Docker
↓
容器
↓
应用
最核心的概念可以记成:
镜像 = 模板
容器 = 镜像运行后的实例
Registry = 存放镜像的仓库
Docker = 管理容器和镜像的平台
Harbor = 企业常用的私有镜像仓库
Docker Compose = 管理多个容器的工具
Dockerfile = 构建镜像的说明书
Volume = 持久化容器数据
Network = 负责容器之间以及容器与外部之间的通信