Docker浅入浅出

180 阅读19分钟

一、前言

以下的路径或者命令可能会因操作系统、Docker版本或安装方式的不同而有所变化,当前docker版本为20.10.16, OS版本 macOS Big Sur 11.3.1

配置目录
~/.docker (或者 /etc/docker 以自己的工作目录为主) 
 ∟ daemon.json: docker配置,如私有镜像仓库地址、加速镜像仓库地址,http代理等 
 ∟ config.json: docker login的镜像仓库地址,其中:linux密码base64存储;mac密码通过Keychain存储在钥匙串中,名称为Docker Credentials。

二、什么是 Docker?

Docker 是一个开源的应用容器引擎,它让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Windows、Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。更重要的是,容器性能开销极低,可以简单、快速的实现应用开发与部署生命周期自动化。正如官方所言: Build and Ship any Application Anywhere,就是:一次构建,到处运行。

Docker的特点

  1. 轻量级与可移植:Docker 容器几乎可以在任何平台上运行,包括虚拟机、物理机、公有云、私有云、个人电脑、服务器等。Docker 容器是基于镜像的,而镜像则是由文件系统层组成,这些层共享和重用,从而减少了磁盘使用和加快了启动时间。
  2. 自动化和版本控制:Docker 容器镜像可以被版本化,并通过 Git 等版本控制系统进行管理。这有助于跟踪和管理容器的变化,并确保在不同环境中部署的应用具有一致性。
  3. 快速部署与扩展:Docker 容器可以在几秒钟内启动,这使得应用可以快速部署和扩展。在云环境中,Docker 容器可以很容易地根据需求自动扩展或缩减。
  4. 简化配置:Docker 容器封装了应用的运行环境,包括文件系统、网络、进程等,使得应用的配置更加简单。开发者可以在开发环境中使用相同的配置在生产环境中部署应用。
  5. 资源隔离:Docker 容器使用 Linux 内核的命名空间(namespaces)和 cgroups 功能来隔离容器之间的进程和资源,确保每个容器都有自己的网络栈、文件系统、进程树等。

命名空间(Namespaces):Docker为每个容器分配了独立的命名空间,包括进程ID命名空间、网络命名空间、用户命名空间等。这使得容器内的进程只能看到与自己相关的资源和环境,而无法看到或影响宿主机或其他容器的进程和资源。
控制组(Cgroups):Cgroups是Linux内核的一个功能,用于限制、记录和隔离进程组所使用的物理资源(如CPU、内存、磁盘I/O等)。Docker通过Cgroups为每个容器设置资源使用上限,确保容器不会占用过多资源,从而影响宿主机或其他容器的正常运行。
文件系统隔离:Docker容器拥有自己独立的文件系统,这个文件系统是从镜像中创建的。容器内的应用程序只能访问这个文件系统,而无法直接访问宿主机的文件系统(除非通过特定的配置和权限设置)。
网络隔离:Docker为容器提供了网络隔离功能,每个容器可以有自己的网络栈,包括IP地址、端口等。这使得容器间的网络通信是隔离的,需要通过网络桥接或其他网络配置才能实现通信。

  1. 微服务架构:Docker 非常适合用于构建微服务架构的应用,每个微服务都可以被封装在一个独立的 Docker 容器中,并通过容器间的网络进行通信。

三、Docker 术语的定义

docker术语

客户端(Docker client)

Docker 客户端 ( docker) 是许多 Docker 用户与 Docker 交互的主要方式。当您使用诸如docker run 之类的命令时,客户端会将这些命令发送到dockerd,从而执行它们。该docker命令使用 Docker API。Docker 客户端可以与多个守护进程通信。

宿主机(Docker HOST)

运行docker容器的主机

守护进程(Docker Daemon)

Docker守护进程是Docker的核心组件之一,它在后台运行并管理Docker容器的生命周期。Docker守护进程监听来自Docker客户端的请求,并根据请求执行相应的操作,如创建容器、启动容器、停止容器等。

Docker容器(Docker Container):

容器是镜像的运行实例,是非持久化的。当Docker镜像被运行时,就会生成一个容器。容器是独立的、轻量级的执行环境,可以包含运行中的应用程序、其依赖项以及一个完整的文件系统。 容器之间是相互隔离的,每个容器都拥有自己的命名空间、网络配置和文件系统,这使得它们可以在同一台物理机上运行而不会相互干扰。

Docker镜像(Docker Image):

镜像是一个将软件环境打包好的模板,用来创建容器的。它包含了运行应用程序所需的所有内容,如代码、运行时环境、库、环境变量和配置文件等。镜像是由多个只读层组成的,这些层在构建过程中被堆叠起来,形成一个完整的文件系统。 镜像创建后是不可变的,但可以通过创建新的镜像来更新应用程序。

Docker注册(Docker Registry):

Registry是存储Docker镜像的地方。它类似于代码仓库,但存储的是镜像文件。Docker Hub是Docker官方提供公共仓库的镜像服务,用户可以从中下载镜像,也可以将自己的镜像推送到Docker Hub或其他镜像服务中。
由于官方docker.hub是国外的镜像服务,访问极其慢,基本国内都设置加速地址或者代理,大型企业则会自建私有镜像服务。然而雪上加霜的是2024.6.6由于监管部门要求大部分镜像服务已关停。

注意:Registry 是一个存储 Docker 镜像的服务,而Repository 通常用于区分不同的软件项目或同一个软件项目的不同版本,用于在 Registry 中组织和存储具有相同名称但标签不同的镜像集合。
一个 Registry 可以包含多个 Repository,一个 Repository 可以包含多个镜像(通过不同的tag区分)。
示例:在 Docker Hub 上,library/ubuntu 是一个 Repository,其中包含了多个版本的 Ubuntu 镜像(如 18.04、20.04 等,每个版本都是一个标签)。

⑴ Docker Registry

Docker官方提供的一个用于存储和分发Docker镜像的开源服务镜像。它是搭建私有仓库的最基本方案,具有轻量级、易部署的特点。比较小巧,适合个人级使用。
通过搭建私有的Docker Registry,企业可以实现对容器镜像的集中管理,确保镜像的安全性和可控性。包含镜像的层次结构及元数据。

  1. 启动registry容器
maple@boog-2 .docker # docker run -d -v /myregistry:/var/lib/registry -p 5000:5000 --restart=always --name registry registry:latest
maple@boog-2 .docker # docker exec -it 3fb3134d07a1 /bin/sh
# cd /var/lib/registry/docker/registry/v2/repositories && ls -la
total 12
drwxr-xr-x    3 root     root          4096 Jul  4 10:51 .
drwxr-xr-x    4 root     root          4096 Jul  4 10:51 ..
drwxr-xr-x    5 root     root          4096 Jul  4 10:51 myimage
/var/lib/registry/docker/registry/v2/repositories # cd myimage/
/var/lib/registry/docker/registry/v2/repositories/myimage # ls
_layers     _manifests  _uploads

push到私有仓储的镜像将存储在宿主机/myregistry, 同时映射容器5000端口宿主机5000
测试方法:curl http://localhost:5000/v2/_catalog,返回json

  1. dameon.json增加配置 insecure-registries": ["localhost:5000"]
  2. 重启docker desktop( linux: systemctl restart docker
  3. 然后,给需要上传的镜像打上一个新的标签,指定Registry的地址和端口:
docker tag myimage:latest localhost:5000/myPrivateImage:latest
  1. 然后就可以进行镜像push/pull到私有Registry:
 docker push localhost:5000/myPrivateImage:latest

⑵ Harbor

Harbor是一个基于Docker Registry由VMware开源的Docker Registry的企业级解决方案,它提供了更丰富的功能,如基于角色的访问控制、审计日志、图形化界面等。Harbor特别适用于需要高安全性和可管理性的企业环境。 【容器化】Harbor 镜像仓

⑶ Frog Artifactory

这是一个全能型的软件包管理解决方案,除了兼容Docker Registry外,还支持npm、Maven等多种包管理格式,适用于大规模和复杂的应用场景。

⑷ 使用第三方云服务

  • 增加前缀: 例如
    • docker pull busybox -> docker pull m.daocloud.io/docker.io/library/busybox
  • 配置镜像加速地址
  • 设置代理:例如Cloudflare

2024年端午节6月6号后,因为神秘原因,绝大部分国内的镜像源都失效了,拉取时提示: error pulling image configuration: download failed after attempts=6: dial tcp x.x.x.x:443: connect: connection timed out,只能切换加速地址、设置代理解决

image.png 注明:以上列表来自 Docker Hub 镜像加速器

Dockerfile:

Dockerfile是一个文本文件,包含了一系列用于构建Docker镜像的指令。这些指令告诉Docker如何获取代码、配置环境、安装依赖项和打包应用程序。 通过执行docker build命令并指定Dockerfile的路径,可以生成一个新的Docker镜像。

Docker Compose:

Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。它使用YAML文件来配置应用程序的服务,并通过单个命令来启动所有服务。Docker Compose简化了多容器应用程序的部署和管理。

四、Docker总体架构

 Docker总体架构 Docker 是一个 C/S 模式的架构,后端是一个松耦合架构,模块各司其职。

  1. 用户使用 Docker Client 与 Docker Daemon 建立通信,并发送请求给后者。
  2. Docker Daemon 作为 Docker 架构中的主体部分,首先提供 Docker Server 的功能使其可以接受 Docker Client 的请求。
  3. Docker Engine 执行 Docker 内部的一系列工作,每一项工作都是以一个 Job 的形式的存在。
  4. Job 的运行过程中,当需要容器镜像时,则从 Docker Registry 中下载镜像,并通过镜像管理驱动 Graphdriver 将下载镜像以 Graph 的形式存储。
  5. 当需要为 Docker 创建网络环境时,通过网络管理驱动 Networkdriver 创建并配置 Docker容器网络环境。
  6. 当需要限制 Docker 容器运行资源或执行用户指令等操作时,则通过 Execdriver 来完成。
  7. Libcontainer 是一项独立的容器管理包,Networkdriver 以及 Execdriver 都是通过 Libcontainer 来实现具体对容器进行的操作。

五、Docker VS 虚拟机

简单来说:
虚拟机(virtual machine)是在操作系统中模拟硬件设备,然后运行另一个操作系统,比如在 Windows 系统里面运行 Ubuntu 系统,这样就可以运行任意的Ubuntu应用了。而Docker仅仅是封装函数库,并没有模拟完整的操作系统。

image.png

具体来说:

  • 更高效的利用系统资源:由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
  • 更快速的启动时间:传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。
  • 一致的运行环境 :开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker镜像 提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
  • 持续交付和部署 :对开发和运维(DevOps)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。 使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合持续集成(Continuous Integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合持续部署系统进行自动部署。 而且使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署该镜像。
  • 更轻松的迁移:由于 Docker 确保了执行环境的一致性,使得应用的迁移更加容易。Docker 可以在很多平台上运行,无论是物理机、虚拟机、公有云、私有云,甚至是笔记本,其运行结果是一致的。因此用户可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况
  • 更轻松的维护和扩展:Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。

六、容器的生命周期

image.png 在这幅图中,我们可以看到,Docker 容器的生命周期里分为五种状态,其分别代表着:

  • Created:容器已经被创建,容器所需的相关资源已经准备就绪,但容器中的程序还未处于运行状态。
  • Running:容器正在运行,也就是容器中的应用正在运行。
  • Paused:容器已暂停,表示容器中的所有程序都处于暂停 ( 不是停止 ) 状态。
  • Stopped:容器处于停止状态,占用的资源和沙盒环境都依然存在,只是容器中的应用程序均已停止。
  • Deleted:容器已删除,相关占用的资源及存储在 Docker 中的管理信息也都已释放和移除。

七、CLI命令

Docker Engine提供了Restful API供Docker Cli调用, 和普通的Web API一样, Docker提供的API也可以直接通过URL进行调用。但是Restful API默认是关闭的,启动docker服务时增加-H=your_ip:your_port开启,swagger接口文档:github.com/gohutool/do…

管理命令

这些是Docker CLI提供的一系列用于管理Docker资源的命令集合。

  • builder:管理构建任务,但通常直接使用docker build命令更为常见。
  • buildx:Docker Buildx是Docker的一个插件,支持多平台构建。表示这是Docker CLI的一个扩展或插件,而不是Docker本身的核心部分。
docker buildx build --platform linux/amd64,linux/arm64 -t myimage:latest .
  • compose:Docker Compose用于定义和运行多容器Docker应用程序。*****同样表示这是一个扩展或插件。
docker compose up
  • config:管理Docker配置,如secrets和configs。
docker config create my_config my_config_file.conf
  • context:管理Docker上下文,允许多个Docker守护进程配置,方便切换。
docker context use my-context
  • manifest:管理Docker镜像的manifest和manifest列表,这对于多平台镜像特别有用。
docker manifest create my_manifest my_image:latest
  • swarm:管理Docker Swarm集群。
docker swarm init
  • node:管理Docker Swarm集群中的节点。
docker node ls
  • plugin:管理Docker插件。
docker plugin install my_plugin
  • sbom:查看Docker镜像的软件物料清单(SBOM),有助于了解镜像中包含的软件组件。
docker sbom my_image:latest
  • scan*:Docker Scan是一个用于扫描Docker镜像中漏洞和配置错误的工具。
docker scan my_image:latest
  • secret:管理Docker secrets,用于在Swarm模式下安全地存储敏感信息。
docker secret create my_secret secret_data.txt
  • service:管理Docker Swarm服务。
docker service ls
  • stack:管理Docker Compose文件定义的堆栈。
docker stack deploy -c docker-compose.yml my_stack
  • system:管理Docker系统,如查看信息、管理存储等。
docker system df
  • trust:管理Docker镜像的信任。
docker trust sign my_image:latest
  • container prune: 删除所有停止的容器。
docker container prune
  • image prune: 删除未被使用的镜像。
docker image prune
  • events: 从服务器获取实时事件。 从服务器获取实时事件。
docker events
  • info: 显示系统范围内的信息。
docker info
  • stats: 显示所有容器资源使用情况的实时流,docker stats就等同于docker container stats)
docker stats
  • checkpoint : 管理容器的检查点。
    • 创建检查点
      docker checkpoint create my_container my_checkpoint
    • 列出检查点
      docker checkpoint ls my_container
    • 恢复检查点
      docker start --checkpoint my_checkpoint my_container
  • help : 帮助。
docker容器
docker COMMAND --help

容器管理

  • attach: 将容器的标准输入、输出、错误流附加到当前终端。
docker attach my_container
  • create: 创建一个新的容器但不启动它。
docker create --name my_container my_image
  • exec: 在运行中的容器内执行命令。
docker exec my_container ls /app
  • kill: 杀死一个或多个正在运行的容器。
docker kill my_container
  • logs: 获取容器的日志输出。
docker logs my_container
  • port: 列出容器的端口映射或特定映射。
docker port my_container
  • ps: 列出容器。
docker ps
  • rename: 重命名容器。
docker rename my_container my_new_container_name
  • restart: 重启一个或多个容器。
docker restart my_container
  • rm: 删除一个或多个容器。
docker rm my_container
  • start: 启动一个或多个已停止的容器。
docker start my_container
  • stop: 停止一个或多个正在运行的容器。
docker stop my_container
  • cp: 在容器和本地文件系统之间复制文件/文件夹。
docker cp my_container:/app/file.txt /local/path/file.txt
  • diff: 检查容器文件系统上文件或目录的更改。
docker diff my_container
  • inspect: 返回Docker对象的底层信息。
docker inspect my_container
  • stats: 显示my_container容器资源使用情况的实时流
docker stats my_container
  • export: 将容器的文件系统导出为 tar 归档文件。
docker export my_container -o my_container.tar
  • top: 显示一个运行中的容器的进程信息。类似于Linux的top命令,但它显示的是容器内部的进程。
docker top mycontainer
  • update: 更新一个或多个容器的配置。这可以包括限制容器的CPU、内存使用,或者调整重启策略等。
#这个命令会将`mycontainer`容器的内存限制更新为512MB,CPUS限制两核。
docker update --memory 512m --cpus 2 mycontainer
  • wait: 阻塞当前shell,直到指定的一个或多个容器停止运行,然后打印出它们的退出代码。这可以用于脚本中,以确保容器完全停止后再继续执行后续操作。
#这个命令会等待`mycontainer`容器停止,并打印出其退出代码。
docker wait mycontainer
  • pause: 暂停一个或多个容器中的所有进程。
docker pause my_container
  • unpause: 恢复一个或多个被暂停的容器中的所有进程。当容器被docker pause命令暂停后,可以使用此命令来恢复它。
# 这个命令会恢复mycontainer容器的所有进程。
docker unpause mycontainer

镜像管理

  • search: 在Docker Hub上搜索镜像。
docker search nginx
  • build: 从Dockerfile构建镜像。
docker build -t my_image:latest .
  • commit: 从容器的更改中创建新镜像。
docker commit my_container my_new_image:latest
  • history: 显示镜像的历史记录。
docker history my_image:latest
  • images: 列出镜像。
docker images
  • import: 从归档文件中导入内容来创建文件系统镜像。
cat my_image.tar | docker import - my_image:latest
  • load: 从归档文件或标准输入中加载镜像。
docker load -i my_image.tar
  • pull: 从注册表中拉取镜像或仓库。
docker pull nginx:latest
  • push: 将镜像或仓库推送到注册表。
docker push my_image:latest
  • rmi: 删除一个或多个镜像。
docker rmi my_image:latest
  • save: 将一个或多个镜像保存到归档文件(默认流式传输到标准输出)。
docker save my_image:latest -o my_image.tar
  • tag: 为一个已存在的镜像创建一个新的标签(tag)。这通常用于更改镜像的引用名称或将其标记为特定版本。
docker tag myimage:latest myimage:v1.0

网络管理

  • 查看网络:
docker network ls
  • 创建网络:
#docker network create 网络名
docker network create hmall
  • 查看网络数据源:
# docker network inspect 网络名
docker network inspect hmall
  • 删除网络:
#docker network rm 网络名
docker nerwork rm hmall
  • 连接容器到网络
docker network connect my_network my_container
  • 断开容器与网络的连接
docker network disconnect my_network my_container

数据卷管理

  • volume:管理Docker卷,用于存储和共享容器数据。
docker volume create my_volume
  • 删除卷
docker volume rm my_volume
  • 挂载卷到容器
docker run -d -v my_volume:/app my_image

八、使用容器的建议

不要创建大型镜像
不要在单个容器中运行多个进程
不要再镜像内保存凭证,不要依赖IP地址
以非root用户运行进程
不要使用“最新”标签
不要利用运行中的容器创建镜像
不要使用单层镜像
不要将数据存放在容器内