Docker 容器技术

Docker 容器技术


一、容器技术概述

1、为什么要学习 Docker?

容器技术是继大数据、云计算之后又一项炙手可热的技术。对 IT 从业者来说,掌握容器技术既是市场需求,也是提升自我价值的重要途径。

Docker 是当前最流行的容器技术代表,Google Trends 中 Docker 的搜索热度持续上升。

学习容器技术可以按照 3W 框架 进行:

  • What:容器是什么?
  • Why:为什么需要容器?
  • How:如何使用容器?

2、什么是容器?

容器是一种轻量级、可移植、自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行。

容器由两部分组成:

  1. 应用程序本身;
  2. 依赖:比如应用程序需要的库或其他软件。

容器在 Host 操作系统的用户空间中运行,与操作系统的其他进程隔离。

3、容器与虚拟机的区别

特性 容器 虚拟机
启动速度 秒级甚至毫秒级 数秒至数十秒
系统内核 共享内核 不共享内核
实现技术 Namespace/Cgroup Hypervisor
隔离效果 进程级别隔离 系统资源级别隔离
资源消耗 容器只是宿主机上的普通进程 有额外资源消耗
运行数量 单机可启动 1000+ 容器 一般不超过 100 台
镜像 分层镜像 非分层镜像
迁移性 优秀 一般

4、为什么需要容器?

核心答案:容器使软件具备了超强的可移植能力。

传统开发面临的问题:

  • 应用包含多种服务,每个服务依赖不同的库和软件包;
  • 部署环境多样:开发 VM、QA 服务器、公有云、私有云、生产集群等。

容器借鉴了"集装箱"思想:任何货物都放进标准集装箱,运输过程无需打开,到达目的地再打开。Docker 将应用及其依赖打包成标准容器,实现"Build Once,Run Anywhere"。

5、Docker 的特性

特性 集装箱 Docker
打包对象 几乎任何货物 任何软件及其依赖
硬件依赖 标准形状和接口 无需修改即可运行在多种平台
隔离性 集装箱可重叠运输 资源、网络、库隔离
自动化 标准接口便于装卸 run、start、stop 等标准化操作
高效性 无需开箱,快速搬运 轻量级,快速启动和迁移
职责分工 货主关心货物,承运方关心运输 开发关心代码,运维关心基础环境

二、容器生态系统

容器生态系统包含三个层次:

  1. 容器核心技术
  2. 容器平台技术
  3. 容器支持技术

1、容器核心技术

容器核心技术是指能够让 container 在 host OS 上运行起来的技术,包括:

  • 容器规范
  • 容器 runtime
  • 容器管理工具
  • 容器定义工具
  • Registries
  • 容器 OS
(1)容器规范

OCI(Open Container Initiative)由 Docker、CoreOS、Google 等公司共同成立,目的是制定开放的容器规范。

目前 OCI 发布了两个规范:

  • runtime spec
  • image format spec

有了这两个规范,不同组织和厂商开发的容器能够在不同的 runtime 上运行,保证了容器的可移植性和互操作性。

(2)容器 runtime

runtime 是容器真正运行的地方,需要跟操作系统 kernel 紧密协作。

主流容器 runtime:

  • lxc:Linux 上老牌的容器 runtime,Docker 最初使用 lxc。
  • runc:Docker 自己开发的容器 runtime,符合 OCI 规范,是 Docker 的默认 runtime。
  • rkt:CoreOS 开发的容器 runtime,符合 OCI 规范。
(3)容器管理工具
  • lxd:lxc 对应的管理工具。
  • docker engine:runc 的管理工具,包含后台 daemon 和 cli。
  • rkt cli:rkt 的管理工具。
(4)容器定义工具
  • docker image:Docker 容器的模板,runtime 依据 docker image 创建容器。
  • dockerfile:包含若干命令的文本文件,可以通过这些命令创建出 docker image。
  • ACI:App Container Image。
(5)Registry

容器通过 image 创建,需要仓库统一存放 image,这个仓库叫做 Registry。

  • Docker Registry:企业可构建私有 Registry。
  • Docker Hub:Docker 为公众提供的托管 Registry。
  • Quay.io:另一个公共托管 Registry。
(6)容器 OS

容器 OS 是专门运行容器的操作系统,通常体积更小、启动更快。

代表:CoreOS、atomic、ubuntu core。

2、容器平台技术

容器平台技术让容器作为集群在分布式环境中运行,包括:

  • 容器编排引擎
  • 容器管理平台
  • 基于容器的 PaaS
(1)容器编排引擎

主流容器编排引擎:

  • docker swarm:Docker 开发。
  • kubernetes:Google 领导开发,支持 Docker 和 CoreOS 容器。
  • mesos + marathon:mesos 是通用集群资源调度平台,与 marathon 一起提供容器编排功能。
(2)容器管理平台

容器管理平台架构在容器编排引擎之上,支持多种编排引擎,提供 application catalog、一键应用部署等功能。

代表:Rancher、ContainerShip。

(3)基于容器的 PaaS

为微服务应用开发人员和公司提供开发、部署和管理应用的平台。

代表:Deis、Flynn、Dokku。

3、容器支持技术

  • 容器网络
  • 服务发现
  • 监控
  • 数据管理
  • 日志管理
  • 安全性
(1)容器网络
  • docker network:Docker 原生网络解决方案。
  • flannel、weave、calico:第三方开源解决方案。
(2)服务发现
  • etcd
  • consul
  • zookeeper
(3)监控
  • docker ps/top/stats
  • docker stats API
  • sysdig
  • cAdvisor/Heapster
  • Weave Scope
(4)数据管理
  • Flocker
(5)日志管理
  • docker logs
  • logspout
(6)安全性
  • OpenSCAP:能够对容器镜像进行扫描,发现潜在漏洞。

三、安装 Docker

1、环境选择

组件 选择
管理工具 Docker Engine
runtime runc
操作系统 CentOS Stream 8

2、安装操作系统

基于 CentOS-Stream-8 模板制作虚拟机,克隆一个虚拟机命名为 docker,配置静态 IP 192.168.108.30,主机名改为 docker

bash 复制代码
[root@localhost ~]# hostnamectl set-hostname docker
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.30/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160

3、卸载旧版本(可选)

bash 复制代码
[root@docker ~]# yum remove docker-ce

4、安装必要工具

bash 复制代码
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 vim
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# yum makecache

5、安装 Docker CE

bash 复制代码
[root@docker ~]# yum install -y docker-ce
[root@docker ~]# systemctl enable docker.service --now

6、验证安装

bash 复制代码
[root@docker ~]# docker --version
Docker version 26.1.3, build b72abbb

[root@docker ~]# systemctl status docker

7、配置镜像加速器

阿里云镜像加速器
bash 复制代码
[root@docker ~]# sudo mkdir -p /etc/docker
[root@docker ~]# sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://spcqvmfn.mirror.aliyuncs.com"]
}
EOF
[root@docker ~]# sudo systemctl daemon-reload
[root@docker ~]# sudo systemctl restart docker

检查:

bash 复制代码
[root@docker ~]# docker info
华为云镜像加速器
bash 复制代码
[root@docker ~]# vi /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com"
  ]
}
[root@docker ~]# systemctl restart docker
[root@docker ~]# docker info

四、运行第一个容器

1、运行 hello-world

bash 复制代码
[root@docker ~]# docker run hello-world

过程说明:

  1. 从本地查找 hello-world 镜像,没找到;
  2. 从 Docker Hub 下载 hello-world 镜像;
  3. 启动 hello-world 容器。

清空实验环境:

bash 复制代码
[root@docker ~]# docker rm -f $(docker ps -aq)
[root@docker ~]# docker rmi -f hello-world

2、运行 httpd 容器

bash 复制代码
[root@docker ~]# docker run -d -p 80:80 httpd

过程说明:

  1. 从 Docker Hub 下载 httpd 镜像;
  2. 启动 httpd 容器,并将容器 80 端口映射到 host 80 端口。

浏览器访问 http://[your host os IP],可以看到 Apache 默认页面。


五、Docker C/S 分离部署

1、环境规划

主机名 IP 作用
docker_server 192.168.108.30 Docker 服务端
docker_client 192.168.108.31 Docker 客户端

2、docker_server 配置

bash 复制代码
[root@localhost ~]# hostnamectl set-hostname docker_server
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.30/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160

安装 Docker:

bash 复制代码
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 vim
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# yum makecache
[root@localhost ~]# yum install -y docker-ce
[root@localhost ~]# systemctl enable docker.service --now

配置镜像加速器:

bash 复制代码
[root@docker_server ~]# vi /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com"
  ]
}
[root@docker_server ~]# systemctl restart docker

配置 Docker 服务监听 TCP:

bash 复制代码
[root@docker_server ~]# vim /usr/lib/systemd/system/docker.service
# 在 ExecStart 参数最后添加 -H tcp://0.0.0.0:2375
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375

[root@docker_server ~]# systemctl daemon-reload
[root@docker_server ~]# systemctl restart docker.service
[root@docker_server ~]# systemctl stop firewalld

验证监听:

bash 复制代码
[root@docker_server ~]# yum install lsof
[root@docker_server ~]# lsof -i :2375

3、docker_client 配置

bash 复制代码
[root@localhost ~]# hostnamectl set-hostname docker_client
[root@localhost ~]# nmcli connection modify ens160 ipv4.method manual ipv4.addresses 192.168.108.31/24 ipv4.gateway 192.168.108.2 ipv4.dns 192.168.108.2 autoconnect yes
[root@localhost ~]# nmcli con up ens160

只安装 Docker 客户端:

bash 复制代码
[root@docker_client ~]# yum install -y yum-utils device-mapper-persistent-data lvm2 vim
[root@docker_client ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@docker_client ~]# yum makecache
[root@docker_client ~]# yum install -y docker-ce-cli

验证:

bash 复制代码
[root@docker_client ~]# docker run hello-world
# 报错:Cannot connect to the Docker daemon...

[root@docker_client ~]# docker -H 192.168.108.30 run hello-world
[root@docker_client ~]# docker -H 192.168.108.30 images

说明:client 只做管理,image 和 container 存储在 server 端。


六、容器架构详解

1、容器发展史

  • 1979:Unix V7 引入 Chroot Jail。
  • 1982:Chroot 加入 BSD。
  • 2000:FreeBSD Jail。
  • 2001:Linux VServer。
  • 2004:Solaris Containers。
  • 2006:Google 推出 Process Containers,后命名为 cgroups。
  • 2008:LXC。
  • 2013:Docker 第一个版本发布。
  • 2014:Google 推出 LMCTFY;CoreOS 发布 rkt。

2、Docker 架构

Docker 采用 Client/Server 架构,主要组件:

  • Docker 客户端(Client)
  • Docker 服务器(Docker daemon)
  • Docker 镜像(Image)
  • Registry
  • Docker 容器(Container)

Docker 内部实现:

  1. 用户使用 Docker Client 与 Docker Daemon 建立通信。
  2. Docker Daemon 提供 Docker Server 功能,接受请求。
  3. Docker Engine 执行内部工作,每项工作以 job 形式存在。
  4. 需要容器镜像时,从 Docker Registry 下载,通过 Graph driver 存储。
  5. 需要网络环境时,通过 Network driver 创建配置。
  6. 需要限制资源或执行用户指令时,通过 Exec driver 完成。
  7. Libcontainer 独立容器管理包,Network driver 和 Exec driver 通过它操作容器。

3、Docker 组件协作

docker run -d -p 80:80 httpd 为例:

  1. Docker 客户端执行 docker run
  2. Docker daemon 发现本地没有 httpd 镜像。
  3. daemon 从 Docker Hub 下载镜像。
  4. 下载完成,镜像 httpd 保存到本地。
  5. Docker daemon 启动容器。
bash 复制代码
[root@docker ~]# docker images
[root@docker ~]# docker ps

七、Docker 镜像

1、最小镜像 hello-world

bash 复制代码
[root@docker ~]# docker pull hello-world
[root@docker ~]# docker images
[root@docker ~]# docker run hello-world

hello-world 的 Dockerfile:

dockerfile 复制代码
FROM scratch
COPY hello /
CMD ["/hello"]

2、base 镜像

base 镜像含义:

  1. 不依赖其他镜像,从 scratch 构建;
  2. 其他镜像可以以它为基础进行扩展。

常见 base 镜像:Ubuntu、Debian、CentOS、Alpine。

bash 复制代码
[root@docker ~]# docker pull centos:7

Linux 操作系统由内核空间和用户空间组成,base 镜像只提供 rootfs,底层共用 Host kernel。

3、镜像分层结构

Docker 镜像采用分层结构,每安装一个软件,就在现有镜像基础上增加一层。

可写的容器层:

  • 容器启动时,一个新的可写层加载到镜像顶部;
  • 所有对容器的改动只发生在容器层;
  • 容器层下面的所有镜像层都是只读的。

对容器增删改查:

操作 具体执行
创建文件 新文件只能被添加在容器层中
删除文件 在容器层记录删除操作,UnionFS 创建 whiteout 文件遮挡
修改文件 将镜像层数据复制到容器层修改,Copy-on-Write
读取文件 由上往下依次查找

4、构建镜像

Docker 提供两种构建镜像的方法:

  1. docker commit
  2. Dockerfile
(1)docker commit
bash 复制代码
[root@docker ~]# docker run -it ubuntu
root@8dbdf6d3d88:/# apt-get update
root@8dbdf6d3d88:/# apt-get install -y vim
# 新窗口查看容器
[root@docker ~]# docker ps
[root@docker ~]# docker commit 8dbdf6d3d88 ubuntu-with-vim
[root@docker ~]# docker images
[root@docker ~]# docker run -it ubuntu-with-vim
root@4d071cf3014f:/# which vim

不推荐使用 docker commit,因为容易出错、效率低、无法审计。

(2)Dockerfile 构建镜像
bash 复制代码
[root@docker ~]# cd /root
[root@docker ~]# vim Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y vim
[root@docker ~]# docker build -t ubuntu-with-vim-dockerfile .

查看镜像分层:

bash 复制代码
[root@docker ~]# docker history ubuntu-with-vim-dockerfile

缓存特性:如果某镜像层已经存在,直接使用缓存。使用 --no-cache 可禁用缓存。

(3)调试 Dockerfile
bash 复制代码
[root@docker ~]# vim Dockerfile
FROM busybox
RUN touch tmpfile
RUN /bin/bash -c "echo continue to build..."
COPY testfile /
[root@docker ~]# docker build -t image-debug .

失败后可用 docker run -it busybox 进入调试。

5、Dockerfile 常用指令

指令 作用
FROM 指定 base 镜像,第一条必须是 FROM
MAINTAINER 设置镜像作者
COPY 将文件从 build context 复制到镜像
ADD 类似 COPY,归档文件会自动解压
ENV 设置环境变量
EXPOSE 指定容器监听端口
VOLUME 声明 volume
WORKDIR 设置当前工作目录
RUN 在容器中运行指定命令
CMD 容器启动时运行指定命令,可被 docker run 参数替换
ENTRYPOINT 设置容器启动时运行的命令

6、RUN vs CMD vs ENTRYPOINT

  • RUN:执行命令并创建新的镜像层,常用于安装软件包。
  • CMD :设置容器启动后默认执行的命令及其参数,但能被 docker run 后面跟的命令行参数替换。
  • ENTRYPOINT:配置容器启动时运行的命令。

Shell 格式与 Exec 格式:

dockerfile 复制代码
# Shell 格式
RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"

# Exec 格式
RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]

最佳实践:

  1. 使用 RUN 指令安装应用和软件包,构建镜像。
  2. 如果 Docker 镜像的用途是运行应用程序或服务,优先使用 Exec 格式的 ENTRYPOINT。
  3. 如果想为容器设置默认启动命令,可使用 CMD。

7、Dockerfile 案例

(1)配置 SSH 镜像
bash 复制代码
[root@docker ~]# vim centos.ssh.dockerfile
FROM centos:8.4.2105
MAINTAINER gaoqiaodong
RUN minorver=8.4.2105 && sed -e "s|^mirrorlist=|#mirrorlist=|g" \
 -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/\$minorver|g" \
 -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum install -y openssh-server
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN echo "root:huawei" | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]

[root@docker ~]# docker build -t centos:ssh -f centos.ssh.dockerfile .
[root@docker ~]# docker run -d -p 2022:22 --name sshtest centos:ssh
[root@docker ~]# ssh root@localhost -p 2022
(2)httpd 镜像
bash 复制代码
[root@docker ~]# vim httpd.dockerfile
FROM centos:8.4.2105
MAINTAINER gaoqiaodong
RUN minorver=8.4.2105 && sed -e "s|^mirrorlist=|#mirrorlist=|g" \
 -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/\$minorver|g" \
 -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum install -y httpd && yum clean all && rm -rf /var/cache/yum
COPY index.html /var/www/html/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

[root@docker ~]# echo Hello world > index.html
[root@docker ~]# docker build -t httpd:centos -f httpd.dockerfile .
[root@docker ~]# docker run -d -p 80:80 --name myweb httpd:centos
[root@docker ~]# curl localhost
(3)自定义 mycentosjava8
bash 复制代码
[root@docker ~]# mkdir ProjectJava ; cd ProjectJava
[root@docker ProjectJava]# vim Dockerfile
FROM centos:8.4.2105
MAINTAINER gaoqiaodong<6946630@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN minorver=8.4.2105 && sed -e "s|^mirrorlist=|#mirrorlist=|g" \
 -e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.aliyun.com/centos-vault/\$minorver|g" \
 -i.bak /etc/yum.repos.d/CentOS-*.repo
RUN yum -y install vim
RUN yum -y install net-tools
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
ADD jdk-8u461-linux-x64.tar.gz /usr/local/java/
ENV JAVA_HOME /usr/local/java/jdk1.8.0_461
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------ok"
CMD /bin/bash

[root@docker ProjectJava]# docker build -t centosjava8:461 .
[root@docker ProjectJava]# docker run -it centosjava8:461 /bin/bash

8、镜像命名与分发

镜像名称格式:

复制代码
[image name] = [repository]:[tag]
完整格式:registry-host:port/username/xxx:tag

打 tag:

bash 复制代码
[root@docker ~]# docker tag myimage-v1.9.1 myimage:1
[root@docker ~]# docker tag myimage-v1.9.1 myimage:1.9
[root@docker ~]# docker tag myimage-v1.9.1 myimage:1.9.1
[root@docker ~]# docker tag myimage-v1.9.1 myimage:latest

9、使用公共 Registry

Docker Hub
bash 复制代码
[root@docker ~]# docker login -u ga0qd
[root@docker ~]# docker tag httpd ga0qd/httpd:v1
[root@docker ~]# docker push ga0qd/httpd:v1
[root@docker ~]# docker pull ga0qd/httpd:v1
华为云 SWR
bash 复制代码
[root@docker ~]# docker login -u cn-east-3@HST3WGZY13FUTQ9ZC32 -p b8e7d74da04a90cb0b1ac08ff894cebe6a8fc039f494ded08cbc64095761aab swr.cn-east-3.myhuaweicloud.com
[root@docker ~]# docker tag httpd:centos swr.cn-east-3.myhuaweicloud.com/gaoqiaodong/centos_httpd:v1
[root@docker ~]# docker push swr.cn-east-3.myhuaweicloud.com/gaoqiaodong/centos_httpd:v1
[root@docker ~]# docker pull swr.cn-east-3.myhuaweicloud.com/gaoqiaodong/centos_httpd:v1

10、搭建本地 Registry

bash 复制代码
[root@docker ~]# docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:2
[root@docker ~]# docker tag httpd:latest localhost:5000/httpd:v1
[root@docker ~]# docker push localhost:5000/httpd:v1
[root@docker ~]# docker pull localhost:5000/httpd:v1

11、企业级私有仓库 Harbor

bash 复制代码
[root@docker ~]# wget https://github.com/goharbor/harbor/releases/download/v2.9.1/harbor-offline-installer-v2.9.1.tgz
[root@docker ~]# tar -xvf harbor-offline-installer-v2.9.1.tgz
[root@docker ~]# mkdir /opt/harbor
[root@docker ~]# mv harbor/* /opt/harbor/
[root@docker ~]# cd /opt/harbor/
[root@docker harbor]# docker load -i harbor.v2.9.1.tar.gz
[root@docker harbor]# cp -ar harbor.yml.tmpl harbor.yml
[root@docker harbor]# vim harbor.yml
# 修改 hostname、harbor_admin_password
[root@docker harbor]# ./prepare
[root@docker harbor]# ./install.sh

登录 Web:http://192.168.108.30

推送镜像:

bash 复制代码
[root@docker ~]# docker login 192.168.108.30
[root@docker ~]# docker tag nginx:latest 192.168.108.30/cloud/nginx:latest
[root@docker ~]# docker push 192.168.108.30/cloud/nginx:latest
[root@docker ~]# docker pull 192.168.108.30/cloud/nginx

卸载 Harbor:

bash 复制代码
[root@docker harbor]# docker compose down
[root@docker harbor]# docker images | grep harbor | awk '{print $1":"$2}' | xargs docker rmi
[root@docker harbor]# rm -rf /data
[root@docker ~]# rm -rf /opt/harbor/

12、镜像常用操作小结

命令 作用
images 显示镜像列表
history 显示镜像构建历史
commit 从容器创建新镜像
build 从 Dockerfile 构建镜像
tag 给镜像打 tag
pull 从 registry 下载镜像
push 将镜像上传到 registry
rmi 删除 Docker host 中的镜像
search 搜索 Docker Hub 中的镜像
save 将本地镜像保存为文件
load 导入本地镜像文件
bash 复制代码
[root@docker ~]# docker save httpd -o httpd.tar
[root@docker ~]# docker load -i images.tar

八、Docker 容器

1、如何运行容器?

docker run = docker create + docker start

bash 复制代码
[root@docker ~]# docker create ubuntu
[root@docker ~]# docker ps -a
[root@docker ~]# docker start ebla0ca86b2
[root@docker ~]# docker run ubuntu pwd

让容器长期运行:

bash 复制代码
[root@docker ~]# docker run ubuntu /bin/bash -c "while true ; do sleep 1 ; echo hahaha; done"
[root@docker ~]# docker run -d ubuntu /bin/bash -c "while true ; do sleep 1 ; echo hahaha; done"

运行 httpd:

bash 复制代码
[root@docker ~]# docker run --name "my_http_server" -d httpd

2、两种进入容器的方法

docker attach
bash 复制代码
[root@docker ~]# docker run -d ubuntu /bin/bash -c "while true ; do sleep 1 ; echo I_am_in_container ; done"
[root@docker ~]# docker attach dc508b94447f

退出:Ctrl+p 然后 Ctrl+q

docker exec
bash 复制代码
[root@docker ~]# docker exec -it <container> bash

区别:

  • attach 直接进入容器启动命令的终端,不会启动新进程;
  • exec 在容器中打开新的终端,可以启动新进程。

查看日志:

bash 复制代码
[root@docker ~]# docker logs -f dc508b94447f

3、容器常用操作

bash 复制代码
docker stop <container>
docker start <container>
docker restart <container>
docker pause <container>
docker unpause <container>
docker rm <container>
docker rm -f $(docker ps -aq)
docker rm -v $(docker ps -aq -f status=exited)

--restart=always

bash 复制代码
[root@docker ~]# docker run -d --restart=always httpd

4、容器状态机

容器状态转换:

  • created
  • running
  • stopped
  • paused
  • deleted

docker create 创建容器处于 Created 状态;docker start 启动;docker rundocker createdocker start 的组合。

5、限制容器资源

内存限额
bash 复制代码
[root@docker ~]# docker run -it -m 200M --memory-swap=300M ubuntu-with-stress --vm 1 --vm-bytes 280M -v

参数:

  • -m--memory:内存使用限额;
  • --memory-swap:内存 + swap 使用限额。
CPU 限额
bash 复制代码
[root@docker ~]# docker run --name "container_A" -it -c 1024 ubuntu-with-stress --cpu 4 -v
[root@docker ~]# docker run --name "container_B" -it -c 512 ubuntu-with-stress --cpu 4 -v

-c--cpu-shares 设置容器使用 CPU 的权重,默认 1024。

6、export 和 import 容器

bash 复制代码
[root@docker ~]# docker export httpd1 -o myhttpd.tar
[root@docker ~]# docker import myhttpd.tar myweb:v1

对比:

  • docker save:保存镜像所有元数据和历史记录;
  • docker export:导出容器文件系统,丢失元数据和历史记录。

7、底层技术:cgroup 和 namespace

  • cgroup:实现资源限额;
  • namespace:实现资源隔离。

namespace 类型:

  • UTS:hostname
  • IPC:共享内存和信号量
  • PID:进程隔离
  • Network:网卡、IP、路由
  • User:用户隔离
bash 复制代码
[root@docker ~]# docker run -h myhost -it ubuntu
root@myhost:/# hostname
myhost

九、Docker 网络

1、none 和 host 网络

bash 复制代码
[root@docker ~]# docker network ls
none 网络
bash 复制代码
[root@docker ~]# docker run -it --network=none busybox
/ # ifconfig

只有 lo,无法与外界通信。

host 网络
bash 复制代码
[root@docker ~]# docker run -it --network=host busybox
/ # ip a

容器共享宿主机的 network namespace。

2、bridge 网络

Docker 安装时会创建 docker0 网桥。容器默认挂到 docker0。

bash 复制代码
[root@docker ~]# yum install -y bridge-utils
[root@docker ~]# brctl show
[root@docker ~]# docker run -itd --name busybox1 busybox
[root@docker ~]# brctl show
[root@docker ~]# docker exec -it busybox1 sh
/ # ip a

查看 bridge 网络配置:

bash 复制代码
[root@docker ~]# docker network inspect bridge

3、自定义网络

bash 复制代码
[root@docker ~]# docker network create --driver bridge my_net
[root@docker ~]# docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2
[root@docker ~]# docker run -it --network=my_net2 --name busybox2 busybox
[root@docker ~]# docker run -it --network=my_net2 --ip 172.22.16.8 --name busybox3 busybox

注意:只有使用 --subnet 创建的网络才能指定静态 IP。

4、容器之间连通性

同一网络中的容器、网关可以通信:

bash 复制代码
/ # ping -c 3 172.22.16.8
/ # ping -c 3 172.22.16.1

不同网络默认不能通信,可通过 docker network connect 将容器加入指定网络:

bash 复制代码
[root@docker ~]# docker network connect my_net2 busybox1

5、容器间通信方式

  1. IP 通信;
  2. Docker DNS Server:--name 容器名通信;
  3. joined 容器:--network=container:web1
bash 复制代码
[root@docker ~]# docker run -it --network my_net2 --name bbox1 busybox
[root@docker ~]# docker run -it --network my_net2 --name bbox2 busybox
[root@docker ~]# docker exec -it bbox2 ping -c 3 bbox1

6、容器访问外部世界

查看 NAT 规则:

bash 复制代码
[root@docker ~]# iptables -t nat -S

容器默认可以访问外网,关键就是 NAT。

7、外部世界访问容器

端口映射:

bash 复制代码
[root@docker ~]# docker run -d -p 80 httpd
[root@docker ~]# docker port 93e6a0ad79c2
[root@docker ~]# docker run -d -p 8080:80 httpd
[root@docker ~]# curl 192.168.108.30:8080

8、实战:安装 tomcat

bash 复制代码
[root@docker ~]# docker search tomcat
[root@docker ~]# docker pull tomcat
[root@docker ~]# docker run -itd -p 8080:8080 tomcat
[root@docker ~]# docker exec -it 92d bash
root@92d78922526b:/usr/local/tomcat# mv webapps.dist/* webapps

再次访问 http://192.168.108.30:8080


十、Docker 存储

1、两类存储资源

  1. 由 storage driver 管理的镜像层和容器层;
  2. Data Volume。

查看 storage driver:

bash 复制代码
[root@docker ~]# docker info | grep "Storage Driver"
Storage Driver: overlay2

2、Data Volume 之 bind mount

bash 复制代码
[root@docker ~]# mkdir htdocs
[root@docker ~]# vim htdocs/index.html
<html><body><h1>This is a file in host file system !</h1></body></html>

[root@docker ~]# docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
[root@docker ~]# curl 127.0.0.1:80

只读权限:

bash 复制代码
[root@docker ~]# docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs:ro httpd

单文件挂载:

bash 复制代码
[root@docker ~]# docker run -d -p 80:80 -v ~/htdocs/index.html:/usr/local/apache2/htdocs/new_index.html httpd

3、Data Volume 之 docker managed volume

bash 复制代码
[root@docker ~]# docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd
[root@docker ~]# docker inspect c75f36c4bf32

Source 为 /var/lib/docker/volumes/.../_data

4、volume container

bash 复制代码
[root@docker ~]# docker create --name vc_data \
 -v ~/htdocs:/usr/local/apache2/htdocs \
 -v /other/useful/tools \
 busybox

[root@docker ~]# docker run --name web1 -d -p 80 --volumes-from vc_data httpd
[root@docker ~]# docker run --name web2 -d -p 80 --volumes-from vc_data httpd
[root@docker ~]# docker run --name web3 -d -p 80 --volumes-from vc_data httpd

5、data-packed volume container

bash 复制代码
[root@docker ~]# vim Dockerfile
FROM busybox:latest
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs

[root@docker ~]# docker build -t datapacked .
[root@docker ~]# docker create --name vc_data datapacked
[root@docker ~]# docker run -d -p 80:80 --volumes-from vc_data httpd

6、volume 生命周期管理

备份、恢复、迁移、销毁:

bash 复制代码
[root@docker ~]# docker run --name bbox -v /test/data busybox
[root@docker ~]# docker volume ls
[root@docker ~]# docker rm bbox
[root@docker ~]# docker volume rm <volume_name>
[root@docker ~]# docker volume prune

7、实战:安装 MySQL

bash 复制代码
[root@docker ~]# docker pull mysql:5.7
[root@docker ~]# docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
[root@docker ~]# docker exec -it cf4065b04c9d bash
bash-4.2# mysql -uroot -p123456
mysql> CREATE DATABASE db01;
mysql> USE db01;
mysql> CREATE TABLE tablea(id int,name varchar(20));

中文乱码解决:

bash 复制代码
[root@docker ~]# mkdir -p /gqd/mysql/conf
[root@docker ~]# vim /gqd/mysql/conf/my.cnf
[mysqld]
character_set_server=utf8
collation_server=utf8_general_ci
[mysql]
default_character_set=utf8

[root@docker ~]# docker run -d -p 3306:3306 --privileged=true \
 -v /gqd/mysql/log:/var/log/mysql \
 -v /gqd/mysql/data:/var/lib/mysql \
 -v /gqd/mysql/conf:/etc/mysql/conf.d \
 -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7

十一、容器监控

1、docker ps

bash 复制代码
[root@docker ~]# docker ps

2、docker top

bash 复制代码
[root@docker ~]# docker top sshtest
[root@docker ~]# docker top sshtest -au

3、docker stats

bash 复制代码
[root@docker ~]# docker stats

4、cAdvisor

bash 复制代码
[root@docker ~]# docker run \
 --volume=/var/run:/var/run:rw \
 --volume=/sys:/sys:ro \
 --volume=/var/lib/docker:/var/lib/docker:ro \
 --publish=8080:8080 \
 --detach=true \
 --name=cadvisor \
 google/cadvisor:latest

访问 http://[Host_IP]:8080


十二、容器日志

bash 复制代码
[root@docker ~]# docker run -d -p 80:80 httpd
[root@docker ~]# docker logs a8286845e6f8
[root@docker ~]# docker logs -f a8286845e6f8

docker logs 能打印自容器启动以来的完整日志,-f 持续打印新日志。


十三、Docker Compose

1、概念

  • 服务(service):一个应用的容器;
  • 项目(project):由一组关联的应用容器组成的完整业务单元,在 docker-compose.yml 中定义。

2、命令说明

bash 复制代码
[root@docker ~]# docker compose version
Docker Compose version v2.27.0

常用命令:

bash 复制代码
docker compose up -d
docker compose down
docker compose ps
docker compose logs
docker compose restart

3、Compose 模板

yaml 复制代码
version: "2"
services:
  webapp:
    image: httpd

4、实战:WordPress

bash 复制代码
[root@docker ~]# mkdir wordpress
[root@docker ~]# cd wordpress/
[root@docker wordpress]# vim docker-compose.yml
services:
  blog:
    image: wordpress:latest
    restart: always
    links:
      - db
    ports:
      - "80:80"
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=root
      - WORDPRESS_DB_PASSWORD=huawei
      - WORDPRESS_DB_NAME=wordpress
  db:
    image: mysql:latest
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=huawei
      - MYSQL_DATABASE=wordpress

[root@docker wordpress]# docker compose config -q
[root@docker wordpress]# docker compose up -d
[root@docker wordpress]# docker ps

浏览器访问 http://192.168.108.30/wp-admin/install.php


十四、Docker 图形界面管理

1、DockerUI

bash 复制代码
[root@docker ~]# docker run -d --name docker.ui --restart always \
 -v /var/run/docker.sock:/var/run/docker.sock \
 -p 8999:8999 joinsunsoft/docker.ui

访问 http://192.168.108.30:8999,默认用户名密码:ginghan/123456

2、Portainer

bash 复制代码
[root@docker ~]# docker volume create portainer_data
[root@docker ~]# docker run -d -p 8000:8000 -p 9443:9443 \
 --name portainer --restart=always \
 -v /var/run/docker.sock:/var/run/docker.sock \
 -v portainer_data:/data \
 portainer/portainer-ce:latest

访问 https://ip:9443,首次访问需要创建管理员账号。

查看 setup token:

bash 复制代码
[root@docker ~]# docker logs portainer

十五、综合实验

1、构建 WordPress

bash 复制代码
[root@docker ~]# docker pull mysql
[root@docker ~]# docker pull wordpress

[root@docker ~]# docker run -d -p 3306:3306 \
 -v /mysql:/var/lib/mysql:z \
 --name mysql \
 -e MYSQL_ROOT_PASSWORD=huawei \
 -e MYSQL_DATABASE=wordpress \
 mysql

[root@docker ~]# docker run -d -p 80:80 \
 --name wordpress \
 --link mysql:mysql \
 -e WORDPRESS_DB_HOST=mysql \
 -e WORDPRESS_DB_USER=root \
 -e WORDPRESS_DB_PASSWORD=huawei \
 -e WORDPRESS_DB_NAME=wordpress \
 wordpress

浏览器访问 http://192.168.108.30/wp-admin/install.php

2、部署 Ghost 开源内容管理系统

bash 复制代码
[root@docker ~]# docker pull ghost
[root@docker ~]# mkdir -p /data/ghost
[root@docker ~]# docker run -d \
 --restart always \
 --name ghost \
 -p 2368:2368 \
 -v /data/ghost:/var/lib/ghost/content \
 -e NODE_ENV=development \
 -e url=http://localhost:2368 \
 ghost

[root@docker ~]# chmod -R 777 /data/ghost/
[root@docker ~]# docker restart ghost
[root@docker ~]# docker ps
[root@docker ~]# docker logs ghost

访问 http://192.168.108.30:2368,进入注册页面:

复制代码
http://192.168.108.30:2368/ghost

十六、总结

本文系统整理了 Docker 容器技术的核心知识,包括:

  1. 容器生态系统的核心技术、平台技术和支持技术;
  2. Docker 安装、镜像加速器、C/S 分离部署;
  3. Docker 架构、镜像分层、Dockerfile 构建;
  4. 容器运行、进入、状态管理、资源限制;
  5. Docker 网络:none、host、bridge、自定义网络、容器通信;
  6. Docker 存储:bind mount、docker managed volume、volume container、data-packed volume container;
  7. 容器监控、日志、Compose、图形化管理;
  8. WordPress、Ghost 等综合实验。

掌握这些内容后,可以比较熟练地使用 Docker 部署和管理容器化应用,并理解容器背后的核心原理。后续可以继续学习 Kubernetes、Harbor、CI/CD、服务网格等进阶技术。

相关推荐
AKAMAI18 小时前
Akamai Valkey 托管数据库:企业 AI 的实时内存解决方案
人工智能·云计算
QYR-分析1 天前
智能车灯升级浪潮!全球车载LED矩阵控制芯片行业研究报告
云计算·汽车
第六种自由1 天前
给 AI Agent 一台云主机:基于 noVNC 的云桌面架构与最小实现
人工智能·架构·云计算
GLAB-Mary1 天前
2026 华为热门认证方向测评:数通 / 安全 / 云计算 / AI / 存储,谁更适配未来就业?
安全·ai·云计算·华为认证·数通·存储
.冰块.1 天前
存储技术基础全解析:DAS/NAS/SAN、RAID 与 RAID2.0 + 详解
云计算·nas·存储技术·das·san
小马同学-2 天前
04 容器存储知识点
运维·docker·云计算
小马同学-2 天前
03 容器网络
运维·云计算
论文复现现场2 天前
课程作业要跑 PyTorch 训练,学校机房不够用去哪租?云 GPU 选型、环境迁移与防丢数据指南
人工智能·pytorch·深度学习·云计算·gpu·cuda
ai小陈2 天前
CUDA Stream实战:让数据传输与GPU计算真正重叠
人工智能·深度学习·ai·pdf·云计算·gpu算力