容器技术基础
什么是容器
容器是一种轻量级的虚拟化技术,它将应用程序及其依赖(库、二进制文件、配置文件等)打包在一个独立的单元中,可以在任何支持容器运行时的环境中一致地运行。
Docker官网:https://www.docker.com/
与传统虚拟机相比,容器具有以下特点:
- 轻量级:容器共享主机操作系统内核,不需要完整的操作系统副本,因此启动速度快、资源占用少。
- 可移植性:容器封装了应用及其依赖,可以在不同环境中一致运行,解决了"在我的机器上能运行"的问题。
- 隔离性:容器提供了进程、文件系统、网络等资源的隔离,但隔离程度低于虚拟机。
- 高效性:容器可以在同一主机上高密度部署,提高资源利用率。
- 快速部署:容器可以快速启动和停止,支持快速扩展和缩减。
容器与虚拟机的区别
容器和虚拟机是两种不同的虚拟化技术,它们有以下主要区别:
特性 | 容器 | 虚拟机 |
---|---|---|
虚拟化级别 | 操作系统级虚拟化 | 硬件级虚拟化 |
内核 | 共享主机内核 | 每个VM有独立内核 |
资源开销 | 轻量级,MB级别 | 重量级,GB级别 |
启动时间 | 秒级 | 分钟级 |
隔离性 | 进程级隔离 | 完全隔离 |
安全性 | 相对较低 | 较高 |
性能 | 接近原生 | 有一定损耗 |
操作系统支持 | 限于主机内核兼容的OS | 几乎任何OS |
Linux容器的核心技术
Linux容器技术基于以下几个核心内核特性:
1. Namespaces(命名空间)
命名空间提供了进程隔离的基础,Linux内核支持以下几种命名空间:
- PID Namespace:进程ID隔离,容器内的进程看不到容器外的进程。
- Network Namespace:网络栈隔离,每个容器有自己的网络设备、IP地址、路由表等。
- Mount Namespace:文件系统挂载点隔离,容器有自己的文件系统视图。
- UTS Namespace:主机名和域名隔离,容器可以有自己的主机名。
- IPC Namespace:进程间通信资源隔离,容器内的进程只能与同一容器内的进程通信。
- User Namespace:用户和组ID隔离,容器内外的用户ID可以映射,提高安全性。
- Cgroup Namespace:控制组隔离,简化容器内进程对Cgroup的视图。
2. Cgroups(控制组)
Cgroups允许限制和监控进程组使用的资源,包括:
- CPU:限制CPU使用率和调度优先级。
- 内存:限制内存使用量和交换空间。
- 磁盘I/O:限制读写速率和优先级。
- 网络:通过tc(Traffic Control)限制网络带宽。
- 设备:控制对设备的访问权限。
3. Union File System(联合文件系统)
联合文件系统允许将多个目录层叠在一起,形成一个统一的视图,是容器镜像分层存储的基础:
- OverlayFS:现代Linux发行版中最常用的联合文件系统。
- AUFS:早期Docker使用的联合文件系统。
- Btrfs:支持写时复制和快照功能的文件系统。
- ZFS:高级文件系统,支持数据压缩、重复数据删除等特性。
4. Seccomp(安全计算模式)
Seccomp限制容器内进程可以使用的系统调用,减少攻击面:
# 示例:使用seccomp配置文件启动容器
docker run --security-opt seccomp=/path/to/seccomp.json nginx
5. Capabilities(能力)
Linux Capabilities将传统的超级用户权限分解为更细粒度的权限集合,容器可以只获得必要的权限:
# 示例:移除所有能力并只添加必要的能力
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
Docker容器技术
Docker是最流行的容器平台,它简化了容器的创建、部署和管理。
Docker架构
Docker采用客户端-服务器架构,主要组件包括:
- Docker客户端(Client):用户通过命令行或API与Docker交互的接口。
- Docker守护进程(Daemon):运行在主机上的后台服务,管理容器的构建、运行和分发。
- Docker镜像(Images):容器的只读模板,包含运行容器所需的文件系统和配置。
- Docker容器(Containers):镜像的运行实例,包含应用及其运行环境。
- Docker仓库(Registry):存储和分发Docker镜像的服务,如Docker Hub。
Docker安装
在不同Linux发行版上安装Docker:
Ubuntu/Debian
# 更新包索引
sudo apt update
# 安装依赖
sudo apt install apt-transport-https ca-certificates curl software-properties-common
# 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 添加Docker仓库
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# 更新包索引
sudo apt update
# 安装Docker
sudo apt install docker-ce docker-ce-cli containerd.io
# 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
sudo docker run hello-world
CentOS/RHEL
# 安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加Docker仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装Docker
sudo yum install docker-ce docker-ce-cli containerd.io
# 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
sudo docker run hello-world
Fedora
# 安装依赖
sudo dnf -y install dnf-plugins-core
# 添加Docker仓库
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
# 安装Docker
sudo dnf install docker-ce docker-ce-cli containerd.io
# 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
sudo docker run hello-world
Docker基本命令
镜像管理
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx:latest
# 列出本地镜像
docker images
# 删除镜像
docker rmi nginx:latest
# 构建镜像
docker build -t myapp:1.0 .
# 保存镜像到文件
docker save -o nginx.tar nginx:latest
# 从文件加载镜像
docker load -i nginx.tar
# 标记镜像
docker tag nginx:latest myregistry.com/nginx:v1
容器管理
# 创建并启动容器
docker run -d --name webserver -p 80:80 nginx
# 列出运行中的容器
docker ps
# 列出所有容器(包括已停止的)
docker ps -a
# 启动/停止/重启容器
docker start webserver
docker stop webserver
docker restart webserver
# 删除容器
docker rm webserver
# 进入容器
docker exec -it webserver bash
# 查看容器日志
docker logs webserver
# 查看容器详细信息
docker inspect webserver
# 查看容器资源使用情况
docker stats webserver
数据管理
# 创建数据卷
docker volume create mydata
# 列出数据卷
docker volume ls
# 查看数据卷详情
docker volume inspect mydata
# 删除数据卷
docker volume rm mydata
# 使用数据卷挂载
docker run -d --name db -v mydata:/var/lib/mysql mysql:5.7
# 使用主机目录挂载
docker run -d --name web -v /host/path:/container/path nginx
网络管理
# 创建网络
docker network create mynetwork
# 列出网络
docker network ls
# 查看网络详情
docker network inspect mynetwork
# 删除网络
docker network rm mynetwork
# 连接容器到网络
docker network connect mynetwork webserver
# 断开容器与网络的连接
docker network disconnect mynetwork webserver
# 使用特定网络启动容器
docker run -d --name db --network mynetwork mysql:5.7
Dockerfile详解
Dockerfile是构建Docker镜像的脚本,包含一系列指令和参数。
基本指令
# 基础镜像
FROM ubuntu:20.04
# 维护者信息
LABEL maintainer="your-email@example.com"
# 设置工作目录
WORKDIR /app
# 复制文件
COPY . .
ADD https://example.com/file.tar.gz /app/
# 运行命令
RUN apt-get update && \
apt-get install -y python3 python3-pip && \
pip3 install -r requirements.txt && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 设置环境变量
ENV NODE_ENV=production \
PORT=3000
# 暴露端口
EXPOSE 3000
# 定义卷
VOLUME ["/data"]
# 设置用户
USER nobody
# 健康检查
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost:3000/ || exit 1
# 入口点
ENTRYPOINT ["python3"]
# 默认命令
CMD ["app.py"]
最佳实践
- 使用多阶段构建:减小最终镜像大小
# 构建阶段
FROM node:14 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
- 合并RUN指令:减少镜像层数
# 不推荐
RUN apt-get update
RUN apt-get install -y package1
RUN apt-get install -y package2
RUN apt-get clean
# 推荐
RUN apt-get update && \
apt-get install -y package1 package2 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
- 使用.dockerignore:排除不需要的文件
# .dockerignore示例
node_modules
npm-debug.log
Dockerfile
.git
.gitignore
README.md
- 使用特定标签而非latest:确保版本一致性
# 不推荐
FROM ubuntu
# 推荐
FROM ubuntu:20.04
- 最小化层数和大小:优化构建速度和镜像大小
# 使用轻量级基础镜像
FROM alpine:3.14
# 安装必要的包并清理
RUN apk add --no-cache python3 py3-pip
Docker Compose
Docker Compose是一个用于定义和运行多容器Docker应用的工具。
安装Docker Compose
# 下载Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 添加执行权限
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker-compose --version
docker-compose.yml示例
version: '3'
services:
web:
build: ./web
ports:
- "80:80"
depends_on:
- db
environment:
- DATABASE_URL=postgres://postgres:password@db:5432/mydb
volumes:
- ./web:/code
networks:
- frontend
- backend
db:
image: postgres:13
environment:
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mydb
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
redis:
image: redis:6
networks:
- backend
networks:
frontend:
backend:
volumes:
postgres_data:
Docker Compose命令
# 启动服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看服务日志
docker-compose logs
# 停止服务
docker-compose stop
# 启动服务
docker-compose start
# 重启服务
docker-compose restart
# 停止并删除容器、网络
docker-compose down
# 停止并删除容器、网络、卷
docker-compose down -v
# 构建或重建服务
docker-compose build
# 执行命令
docker-compose exec web bash
# 查看配置
docker-compose config
Kubernetes容器编排
Kubernetes(K8s)是一个开源的容器编排平台,用于自动化容器的部署、扩展和管理。
Kubernetes架构
Kubernetes集群由以下组件组成:
-
控制平面组件:
- kube-apiserver:API服务器,是控制平面的前端。
- etcd:一致且高可用的键值存储,用于存储集群数据。
- kube-scheduler:监视新创建的Pod,并决定在哪个节点上运行。
- kube-controller-manager:运行控制器进程,如节点控制器、副本控制器等。
- cloud-controller-manager:与云提供商的API交互。
-
节点组件:
- kubelet:确保容器在Pod中运行。
- kube-proxy:维护节点上的网络规则,实现服务抽象。
- 容器运行时:如Docker、containerd、CRI-O等,负责运行容器。
Minikube安装
Minikube是一个工具,可以在本地运行Kubernetes:
# 安装Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# 安装kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# 启动Minikube
minikube start
# 验证安装
kubectl get nodes
Kubernetes基本概念
Pod
Pod是Kubernetes中最小的可部署单元,可以包含一个或多个容器:
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
# 创建Pod
kubectl apply -f pod.yaml
# 查看Pod
kubectl get pods
# 查看Pod详情
kubectl describe pod nginx-pod
# 删除Pod
kubectl delete pod nginx-pod
Deployment
Deployment提供了Pod的声明式更新和扩展能力:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19
ports:
- containerPort: 80
# 创建Deployment
kubectl apply -f deployment.yaml
# 查看Deployment
kubectl get deployments
# 扩展Deployment
kubectl scale deployment nginx-deployment --replicas=5
# 更新Deployment
kubectl set image deployment/nginx-deployment nginx=nginx:1.20
# 查看更新状态
kubectl rollout status deployment/nginx-deployment
# 回滚更新
kubectl rollout undo deployment/nginx-deployment
Service
Service定义了Pod的访问方式:
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
type: ClusterIP # 可选值:ClusterIP, NodePort, LoadBalancer, ExternalName
# 创建Service
kubectl apply -f service.yaml
# 查看Service
kubectl get services
# 查看Service详情
kubectl describe service nginx-service
# 删除Service
kubectl delete service nginx-service
ConfigMap和Secret
ConfigMap用于存储非敏感配置,Secret用于存储敏感信息:
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
app.properties: |
environment=production
log_level=info
database.properties: |
host=db.example.com
port=5432
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
username: YWRtaW4= # base64编码的"admin"
password: cGFzc3dvcmQ= # base64编码的"password"
# 创建ConfigMap和Secret
kubectl apply -f configmap.yaml
kubectl apply -f secret.yaml
# 在Pod中使用ConfigMap
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: config-volume
mountPath: /etc/config
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: log_level
volumes:
- name: config-volume
configMap:
name: app-config
# 在Pod中使用Secret
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:1.0
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: app-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secret
key: password
持久卷(PV)和持久卷声明(PVC)
PV提供了存储资源,PVC是对PV的请求:
# pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-volume
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/pv0001
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
# 在Pod中使用PVC
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: data-volume
mountPath: /data
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: pv-claim
Helm包管理器
Helm是Kubernetes的包管理器,简化了应用的部署和管理:
# 安装Helm
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
# 添加仓库
helm repo add stable https://charts.helm.sh/stable
# 更新仓库
helm repo update
# 搜索Chart
helm search repo nginx
# 安装Chart
helm install my-nginx stable/nginx
# 查看已安装的Release
helm list
# 升级Release
helm upgrade my-nginx stable/nginx --set replicaCount=3
# 回滚Release
helm rollback my-nginx 1
# 卸载Release
helm uninstall my-nginx
# 创建自己的Chart
helm create mychart
容器安全
容器安全是容器技术应用中的重要考虑因素。
容器安全最佳实践
-
使用最小基础镜像:
- 使用Alpine或Distroless等最小化镜像
- 减少攻击面和漏洞风险
-
定期更新镜像:
- 保持基础镜像和依赖的更新
- 使用自动化工具扫描镜像漏洞
-
不要以root用户运行容器:
# 在Dockerfile中创建非root用户 RUN adduser -D appuser USER appuser
-
限制容器资源:
# 限制CPU和内存 docker run --cpus=0.5 --memory=512m nginx
-
使用只读文件系统:
# 使用只读文件系统,只有特定目录可写 docker run --read-only --tmpfs /tmp nginx
-
使用安全扫描工具:
- Clair
- Trivy
- Anchore Engine
- Docker Bench for Security
-
实施网络分段:
- 使用自定义网络隔离容器
- 限制容器间通信
-
使用安全计算模式(seccomp):
# 使用seccomp配置文件 docker run --security-opt seccomp=/path/to/seccomp.json nginx
-
限制容器能力(capabilities):
# 移除所有能力并只添加必要的能力 docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
-
使用内容信任和镜像签名:
# 启用Docker内容信任 export DOCKER_CONTENT_TRUST=1 docker push myregistry.com/myimage:1.0
容器安全工具
-
Docker Bench for Security:
# 运行Docker安全基准测试 docker run --net host --pid host --userns host --cap-add audit_control \ -v /var/lib:/var/lib \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/lib/systemd:/usr/lib/systemd \ -v /etc:/etc --label docker_bench_security \ docker/docker-bench-security
-
Trivy:
# 安装Trivy sudo apt-get install wget apt-transport-https gnupg lsb-release wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list sudo apt-get update sudo apt-get install trivy # 扫描镜像 trivy image nginx:latest
-
Falco:
# 安装Falco curl -s https://falco.org/repo/falcosecurity-3672BA8F.asc | apt-key add - echo "deb https://download.falco.org/packages/deb stable main" | tee -a /etc/apt/sources.list.d/falcosecurity.list apt-get update -y apt-get install -y falco # 启动Falco systemctl start falco
容器网络
容器网络是容器技术的重要组成部分,它使容器能够相互通信以及与外部世界通信。
Docker网络模式
Docker支持多种网络模式:
-
Bridge网络:默认网络模式,容器通过网桥连接。
# 创建自定义桥接网络 docker network create --driver bridge my-bridge-network # 使用自定义网络启动容器 docker run --network my-bridge-network nginx
-
Host网络:容器使用主机的网络命名空间。
# 使用host网络启动容器 docker run --network host nginx
-
None网络:容器没有网络接口。
# 使用none网络启动容器 docker run --network none nginx
-
Overlay网络:用于Docker Swarm中的多主机通信。
# 创建overlay网络 docker network create --driver overlay my-overlay-network