您现在的位置是:首页 >技术杂谈 >【Docker】网站首页技术杂谈

【Docker】

茉菇 2025-02-11 12:01:03
简介【Docker】

一、概述

1、Docker为什么出现?

开发和运维两套环境,而环境配置十分麻烦。如在Windows上开发,要发布到Linux上运行。

Docker给以上问题提出了解决方案:Java --- Jar(环境)---打包项目带上环境(镜像)---Docker仓库(应用商店)---下载镜像---直接运行

Docker的思想来自于集装箱,核心思想:隔离。即将应用打包装箱,每个箱子是互相隔离的,可以将服务器利用到极致。

虚拟机Docker
linux centos原生镜像(一个电脑)隔离镜像(最核心的环境 +jdk +mysql等)
需要开启多个虚拟机运行镜像就可以了
几GB几MB

2、Docker能做什么?

传统虚拟机 vs Docker :

20201209124302

Docker的优点:

  • 不模拟完整的操作系统,系统内核(kernel)非常小,更少的抽象层(GuestOS:如Centos)
  • 容器内的应用直接运行在宿主机的内核,容器本身没有自己的内核,也没有虚拟硬件。
  • 每个容器相互隔离,内部都有属于自己的文件系统,互不影响。

Docker实现DevOps(开发、运维):

  • 应用更快速的交付和部署
    打包镜像发布测试,一键运行;不再需要写大量帮助文档,安装程序
  • 更便捷的升级和扩缩容?
    部署应用就和搭积木一样
  • 更简单的系统运维
    开发和测试的环境高度一致
  • 更高效的计算资源利用
    内核级别的虚拟化,可以在一个物理机上运行很多的容器实例,服务器性能可以被压榨到极致。

3、Docker的基本组成

20201208171750

  • 镜像(image):镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。相当于一个模板,通过这个模板来创建容器服务,可以通过一个镜像创建多个容器。
  • 容器(container):独立运行一个或一组应用/基本命令有:启动,停止,删除等/可理解为一个简单的linux系统。
  • 仓库(repository):存放镜像的地方(公有/私有)

4、Docker运行原理

Docker是一个Client-Server结构的系统,以守护进程运行在主机上。通过Socket从客户端进行访问。

二、安装

1、Linux 环境安装 Docker

# 1、更新系统软件包
yum update -y

# 2、安装yum工具包
yum install -y yum-utils

# 3、卸载 Docker
yum remove docker 
                  docker-client 
                  docker-client-latest 
                  docker-common 
                  docker-latest 
                  docker-latest-logrotate 
                  docker-logrotate 
                  docker-selinux 
                  docker-engine-selinux 
                  docker-engine 
                  docker-ce

# 4、添加镜像(阿里云)https://download.docker.com/linux/centos/docker-ce.repo
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 5、安装Docker
yum install -y docker-ce docker-ce-cli containerd.io

# 6、启动Docker
systemctl start docker

# 7、允许开机自启动
systemctl enable docker

# 8、验证
docker --version

# 9、配置 Docker 镜像加速
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.m.daocloud.io",
    "https://dockerproxy.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://docker.nju.edu.cn",
    "https://vp5v3vra.mirror.aliyuncs.com",
    "https://docker.registry.cyou",
    "https://docker-cf.registry.cyou",
    "https://dockercf.jsdelivr.fyi",
    "https://docker.jsdelivr.fyi",
    "https://dockertest.jsdelivr.fyi",
    "https://mirror.baidubce.com",
    "https://docker.m.daocloud.io",
    "https://docker.nju.edu.cn",
    "https://docker.mirrors.sjtug.sjtu.edu.cn",
    "https://docker.mirrors.ustc.edu.cn",
    "https://mirror.iscas.ac.cn",
    "https://docker.rainbond.cc"
  ]
}
EOF

# 10、重启docker服务
systemctl daemon-reload
systemctl restart docker

卸载Docker

yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker

启动 hello-world:

docker run hello-world		# 本地没有会自动到远程仓库(/etc/docker/daemon.json)取下载
docker images				# 查看镜像会发现本地多出一个镜像hello-world

三、命令

Docker 常见基础命令:

在这里插入图片描述

1、帮助命令

1.1 Docker 版本信息

[root@localhost ~]# docker --version
Docker version 26.1.4, build 5650f9b

[root@localhost ~]# docker version
Client: Docker Engine - Community
 Version:           26.1.4
 API version:       1.45
 Go version:        go1.21.11
 Git commit:        5650f9b
 Built:             Wed Jun  5 11:32:05 2024
 OS/Arch:           linux/arm64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          26.1.4
  API version:      1.45 (minimum version 1.24)
  Go version:       go1.21.11
  Git commit:       de5c9cf
  Built:            Wed Jun  5 11:31:16 2024
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.6.33
  GitCommit:        d2d58213f83a351ca8f528a95fbd145f5654e957
 runc:
  Version:          1.1.12
  GitCommit:        v1.1.12-0-g51d5e94
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

1.2 Docker 系统信息

[root@localhost ~]# docker info
Client: Docker Engine - Community
 Version:    26.1.4
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.14.1
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.27.1
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 2
 Server Version: 26.1.4
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: d2d58213f83a351ca8f528a95fbd145f5654e957
 runc version: v1.1.12-0-g51d5e94
 init version: de40ad0
 Security Options:
  seccomp
   Profile: builtin
 Kernel Version: 5.11.12-300.el7.aarch64
 Operating System: CentOS Linux 7 (AltArch)
 OSType: linux
 Architecture: aarch64
 CPUs: 2
 Total Memory: 1.425GiB
 Name: localhost.localdomain
 ID: c1a0a9fe-896a-4ca1-9972-16dc7dbca8f1
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  https://docker.m.daocloud.io/
  https://dockerproxy.com/
  https://docker.mirrors.ustc.edu.cn/
  https://docker.nju.edu.cn/
  https://vp5v3vra.mirror.aliyuncs.com/
  https://docker.registry.cyou/
  https://docker-cf.registry.cyou/
  https://dockercf.jsdelivr.fyi/
  https://docker.jsdelivr.fyi/
  https://dockertest.jsdelivr.fyi/
  https://mirror.baidubce.com/
  https://docker.mirrors.sjtug.sjtu.edu.cn/
  https://mirror.iscas.ac.cn/
  https://docker.rainbond.cc/
 Live Restore Enabled: false

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

1.3 docker 帮助信息

[root@localhost ~]# docker --help

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Common Commands:
  run         Create and run a new container from an image
  exec        Execute a command in a running container
  ps          List containers
  build       Build an image from a Dockerfile
  pull        Download an image from a registry
  push        Upload an image to a registry
  images      List images
  login       Log in to a registry
  logout      Log out from a registry
  search      Search Docker Hub for images
  version     Show the Docker version information
  info        Display system-wide information

Management Commands:
  builder     Manage builds
  buildx*     Docker Buildx
  compose*    Docker Compose
  container   Manage containers
  context     Manage contexts
  image       Manage images
  manifest    Manage Docker image manifests and manifest lists
  network     Manage networks
  plugin      Manage plugins
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Swarm Commands:
  swarm       Manage Swarm

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit codes

Global Options:
      --config string      Location of client config files (default
                           "/root/.docker")
  -c, --context string     Name of the context to use to connect to the
                           daemon (overrides DOCKER_HOST env var and
                           default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket to connect to
  -l, --log-level string   Set the logging level ("debug", "info", "warn",
                           "error", "fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default
                           "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default
                           "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default
                           "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Run 'docker COMMAND --help' for more information on a command.

For more help on how to use Docker, head to https://docs.docker.com/go/guides/

2、镜像命令

2.1 镜像管理

docker image 命令用于管理 Docker 镜像,它提供了多个子命令来执行不同的镜像管理任务。

语法:

docker image COMMAND

参数说明:

Commands:
  build       从 Dockerfile 构建镜像。这个命令会读取指定的 Dockerfile,并根据其中的指令构建一个新的镜像。
  history     显示镜像的历史。这个命令会列出镜像的每一层以及相关的创建信息,有助于理解镜像的构建过程。
  import      从归档文件导入镜像。你可以将一个包含文件系统的归档文件(如 tar 包)导入为 Docker 镜像。
  inspect     显示镜像的详细信息。这个命令会输出镜像的 JSON 格式详细信息,包括配置、层信息、环境变量等。
  load        从归档文件或标准输入加载镜像。这个命令通常用于加载之前使用 docker save 命令保存的镜像。
  ls          列出镜像。这个命令会列出本地存储的所有 Docker 镜像。
  prune       移除未使用的镜像。这个命令会删除所有未被容器使用的镜像,以节省存储空间。
  pull        从镜像仓库下载镜像。这个命令会从指定的镜像仓库(默认为 Docker Hub)下载镜像到本地。
  push        将镜像上传到镜像仓库。这个命令会将本地镜像上传到指定的镜像仓库,以便其他人可以拉取和使用。
  rm          移除一个或多个镜像。这个命令会删除指定的 Docker 镜像。
  save        将镜像保存到归档文件。这个命令会将一个或多个镜像保存为 tar 归档文件,以便可以在其他地方加载和使用。
  tag         为镜像创建标签。这个命令会为指定的镜像创建一个新的标签(或别名),这有助于组织和引用镜像。

2.2 列出本地镜像

列出本地存储的 Docker 镜像:

docker images [OPTIONS] [REPOSITORY[:TAG]]

等价命令: docker image ls, docker image list, docker images

参数说明:

REPOSITORY:镜像的仓库名称。

TAG:镜像的标签,用于指定要列出的镜像版本。如果不指定仓库和标签,则列出所有镜像。

Options:
  -a, --all             显示所有镜像,包括中间层镜像(默认情况下,这些镜像是被隐藏的)
      --digests         显示镜像的摘要信息。摘要是一种唯一标识镜像内容的方式
  -f, --filter filter   根据提供的条件过滤输出结果。例如,你可以根据镜像的标签、创建时间或大小来过滤镜像。
      --format string   使用自定义模板格式化输出。Docker 提供了几种预定义的格式:
                        'table':            Print output in table format
                        列名 (default)'table TEMPLATE':   Print output in table format
                        使用 Go 模板语言:
                        'json':             Print in JSON format
                        'TEMPLATE':         Print output using the given Go
                        template.
                        更多格式移步 https://docs.docker.com/go/formatting/
      --no-trunc        不截断输出信息。默认情况下,为了节省空间,一些信息(如镜像 ID 和仓库名称)可能会被截断。使用这个选项可以显示完整的信息。
  -q, --quiet           仅显示镜像 ID,不显示其他信息。

2.3 搜索镜像

在Docker Hub 上搜索镜像

docker search [OPTIONS] TERM

TERM:镜像名

Options:
	-f, --filter filter   # 根据提供的条件过滤输出结果
	    --format string   # 自定义输出格式
	    --limit int       # 设置最大搜索结果数量
	    --no-trunc        # 不截断输出结果

示例:

# 搜索 Docker Hub 上所有官方的 "nginx" 镜像,并且显示完整的结果信息
docker search --filter=is-official=true --no-trunc nginx

2.4 登陆镜像网

docker login 命令用于向 Docker 镜像仓库(registry)进行登录认证。当你需要推送(push)镜像到某个仓库,或者从需要认证的私有仓库拉取(pull)镜像时,你需要先使用该命令进行登录。

语法:

docker login [OPTIONS] [SERVER]

参数说明:

SERVER:指定要登录的 Docker 镜像仓库的地址。如果不指定,Docker 将会使用默认配置的仓库地址,这个地址通常由 Docker daemon 的配置文件指定。

Options:
  -p, --password string   直接在命令行中指定登录密码。出于安全考虑,通常不推荐在命令行中直接输入密码,因为这样可能会被其他用户通过命令历史等方式获取。
      --password-stdin    从标准输入(stdin)读取密码。这是一个更安全的方式,因为它允许你通过管道或其他方式将密码传递给 docker login 命令,而不会在命令行历史中留下痕迹。
  -u, --username string   指定登录的用户名。

示例:

# 直接在命令行中指定用户名和密码(不推荐,因为不安全):
docker login -u myusername -p mypassword myregistry.com
# 使用 --password-stdin 选项从标准输入读取密码
echo "mypassword" | docker login -u myusername --password-stdin myregistry.com
# 将密码保存在一个文件中,并使用 cat 命令将其传递给 docker login:
cat mypasswordfile.txt | docker login -u myusername --password-stdin myregistry.com
# 登陆默认仓库
docker login -u myusername

2.5 登出镜像网

docker logout 命令用于从 Docker 注册中心登出。

语法:

docker logout [SERVER]

参数说明:

[SERVER]:这是可选的。它指定了你要登出的注册中心的服务器地址。如果你没有指定服务器,Docker 将使用守护进程(daemon)配置中定义的默认注册中心。

2.6 拉取镜像

从镜像仓库(默认为 Docker Hub)下载镜像.

语法:

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

别名(即等价命令):

docker image pull 和 docker pull

参数说明:

NAME:镜像名称。
TAG:镜像标签,用于指定镜像的版本。如果不指定标签,则默认使用 latest 标签。
DIGEST:镜像摘要,用于确保下载的镜像完全匹配特定的内容。

Options:
  -a, --all-tags                # 下载仓库中的所有标签的镜像
      --disable-content-trust   # 跳过镜像验证。默认情况下,如果启用了内容信任(Content Trust),Docker 会验证镜像的签名。使用这个选项可以跳过签名验证。但请注意,这可能会使你下载到未签名或签名不正确的镜像。
      --platform string         # 设置平台。如果镜像仓库支持多平台,你可以使用这个选项来指定要拉取的镜像的平台。
      -q, --quiet               # 抑制详细输出。默认情况下,docker pull 命令会显示拉取镜像的进度和详细信息。使用这个选项可以只显示镜像的名称和标签,而不显示其他信息。

示例:

# 从 Docker Hub 下载一个名为 nginx 的镜像,并指定标签为 1.21
docker pull nginx:1.21

2.7 查看镜像信息

docker inspect 命令用于返回 Docker 对象的低级信息。这些对象可以是容器(Container)、镜像(Image)、网络(Network)、卷(Volume)等

语法:

docker inspect [OPTIONS] NAME|ID [NAME|ID...]

参数说明:

NAME|ID [NAME|ID...]:指定要检查的 Docker 对象的名称或 ID。你可以指定一个或多个对象,每个对象之间用空格分隔。

Options:
  -f, --format string   使用自定义模板格式化输出:
                        'json':             以 JSON 格式打印输出。这是获取结构化数据的最简单方式
                        'TEMPLATE':         使用指定的 Go 模板打印输出。Go 模板提供了强大的格式化能力,允许你提取和重组信息以满足特定需求。
                        更多格式信息移步:https://docs.docker.com/go/formatting/ 
  -s, --size            如果类型是容器,则显示总文件大小。这个选项对于了解容器占用的磁盘空间非常有用。
      --type string     返回指定类型的 JSON。这个选项允许你指定要返回信息的 Docker 对象类型,例如 container、image、network 或 volume。如果你只对特定类型的对象感兴趣,这个选项可以帮助你过滤掉不需要的信息。

示例:

# 以 JSON 格式获取特定容器的详细信息
docker inspect --format='{{json .}}' <CONTAINER_ID>

# 返回容器的名称和状态,以自定义的格式显示
docker inspect --format='{{.Name}} - {{.State.Status}}' <CONTAINER_ID>

2.8 镜像打标签

docker tag 命令用于为 Docker 镜像创建一个新的标签(tag)。这个命令允许你将一个已存在的镜像标记为一个新的名称或标签,这在很多场景下都非常有用,比如当你想要将镜像推送到远程仓库时,可能需要为其指定一个符合仓库命名规则的标签。

语法:

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

别名(即等价命令):

docker image tag, docker tag

参数说明:

SOURCE_IMAGE[:TAG]:指定源镜像的名称和标签。如果标签被省略,则默认使用源镜像的最新标签(latest)。
TARGET_IMAGE[:TAG]:指定目标镜像的名称和标签。你需要为新镜像指定一个唯一的名称(可能包括仓库地址)和标签。如果标签被省略,则同样默认使用 latest。

示例:

# 创建一个新的标签 v2.0
docker tag myimage:v1.0 myimage:v2.0

# 如果你想要将这个镜像推送到一个远程仓库,比如 Docker Hub 上的 myusername/myrepo,并为其指定标签 latest,你可以这样做:
docker tag myimage:v1.0 myusername/myrepo:latest

docker tag 命令只是在本地 Docker 守护进程中创建了镜像的一个新标签,它并没有复制或修改镜像数据。因此,这个操作是非常快速的。

2.9 推送镜像

docker push 命令用于将本地镜像上传到镜像仓库中.

语法:

docker push [OPTIONS] NAME[:TAG]

别名(即等价命令):

docker image push, docker push

参数说明:

Options:
  -a, --all-tags                上传镜像的所有标签到仓库。如果你有一个镜像有多个标签(例如,myimage:latest 和 myimage:1.0),使用这个选项可以一次性上传所有标签。
      --disable-content-trust   跳过镜像签名。默认情况下,如果启用了内容信任(Content Trust),Docker 会要求镜像被签名。使用这个选项可以跳过签名检查。注意,默认值是 true,但这里的描述可能有些误导,因为通常我们期望的是如果启用了内容信任,则默认行为是要求签名,而使用此选项来禁用它。
  -q, --quiet                   抑制详细输出。使用这个选项,命令执行时不会显示详细的进度信息。

示例:

# 上传一个名为 myimage,标签为 latest 的镜像到仓库:
docker push myimage:latest
# 上传 myimage 的所有标签到仓库:
docker push -a myimage
# 安静模式下上传 myimage:latest,不显示详细输出:
docker push -q myimage:latest

使用 docker push 命令时,需要确保你有权限向目标仓库推送镜像,并且目标仓库的地址(如果不是 Docker Hub)需要在镜像名称中指定(例如,myregistry.com/myimage:latest)。

2.10 删除镜像

docker rmi 命令(或其别名 docker image rm、docker image remove)用于删除一个或多个 Docker 镜像。

语法:

docker rmi [OPTIONS] IMAGE [IMAGE...]

别名(等价命令):

docker image rm, docker image remove, docker rmi

参数说明:

Options:
  -f, --force      强制删除镜像,即使有容器正在使用它。这通常会导致正在运行的容器停止并删除,但请注意,这可能会丢失数据。在使用此选项时要格外小心。
      --no-prune   默认情况下,当删除一个镜像时,Docker 也会删除所有未被标记(untagged)的父镜像。这些父镜像可能仍然被其他镜像所依赖。使用 --no-prune 选项可以防止删除这些未被标记的父镜像。但是,请注意,这可能会导致磁盘空间占用增加,因为未被标记的父镜像仍然会保留在磁盘上。

示例:

# 删除名为 myimage 的镜像:
docker rmi myimage
# 强制删除名为 myimage 的镜像,即使有容器正在使用它:
docker rmi -f myimage
# 删除多个镜像(myimage1 和 myimage2):
docker rmi myimage1 myimage2

注意事项:

  • 在删除镜像之前,请确保没有容器正在使用该镜像,除非你打算强制删除它。
  • 使用 --force 选项时要格外小心,因为它可能会导致数据丢失。
  • 如果你不确定哪些镜像可以安全删除,可以使用 docker images 命令来查看所有镜像及其依赖关系。

docker rmi 用于管理和清理 Docker 镜像。但是,在使用它时要谨慎,以避免意外删除重要镜像或导致数据丢失。

2.11 导出镜像

docker save 命令用于将一个或多个 Docker 镜像保存到一个 tar 归档文件中。这个命令通常用于备份镜像、迁移镜像到另一个系统或者在没有网络连接的情况下分发镜像。

语法:

docker save [OPTIONS] IMAGE [IMAGE...]

别名(即等价命令):

docker image save, docker save

参数说明:

Options:
  -o, --output string   将归档内容写入到指定的文件中,而不是标准输出。你需要提供一个有效的文件路径来保存 tar 归档。如果不指定 -o 选项,归档内容将被输出到标准输出。

示例:

# 将名为 myimage 的镜像保存到一个名为 myimage.tar 的文件中:
docker save -o myimage.tar myimage
# 将多个镜像(myimage1 和 myimage2)保存到一个名为 images.tar 的文件中:
docker save -o images.tar myimage1 myimage2
# 可以通过管道将其传输到另一个命令:
docker save myimage | gzip > myimage.tar.gz

使用 docker save 命令时,请确保你有足够的权限来访问和保存指定的镜像。保存成功后,你可以使用 docker load 命令来加载这个 tar 归档文件中的镜像。

2.12 导入镜像

docker load 命令用于从 tar 归档文件或标准输入(STDIN)中加载一个镜像。

语法:

docker load [OPTIONS]

别名(即等价命令):

docker image load, docker load

参数说明:

Options:
  -i, --input string   从 tar 归档文件中读取镜像,而不是从标准输入。你需要指定归档文件的路径。如果不使用此选项,docker load 将从标准输入读取数据。
  -q, --quiet          抑制加载输出。使用这个选项时,命令执行时不会显示加载的进度和成功消息。## 3、容器命令

示例:

# 从名为 myimage.tar 的 tar 归档文件中加载镜像:
docker load -i myimage.tar
# 从标准输入加载镜像(例如,通过管道传输):
cat myimage.tar | docker load
# 安静模式下加载镜像,不显示加载输出:
docker load -q -i myimage.tar
cat myimage.tar | docker load -q

使用 docker load 命令时,确保你有一个有效的 Docker 镜像 tar 归档文件,或者能够通过标准输入提供这样的数据。加载成功后,镜像将出现在你的本地 Docker 镜像存储中,并可以使用 docker images 命令查看。

3、容器命令

3.1 容器管理

[root@localhost ~]# docker container --help

Usage:  docker container COMMAND

Manage containers

Commands:
  attach      将本地标准输入、输出和错误流附加到正在运行的容器上。
  commit      从容器的更改中创建一个新镜像。
  cp          在容器和本地文件系统之间复制文件/文件夹。
  create      创建一个新容器。
  diff        检查容器文件系统上文件或目录的更改。
  exec        在正在运行的容器中执行命令。
  export      将容器的文件系统导出为 tar 存档。
  inspect     显示一个或多个容器的详细信息。
  kill        杀死一个或多个正在运行的容器。
  logs        获取容器的日志。
  ls          列出容器。
  pause       暂停一个或多个容器内的所有进程。
  port        列出容器的端口映射或特定映射。
  prune       删除所有已停止的容器。
  rename      重命名容器。
  restart     重启一个或多个容器。
  rm          删除一个或多个容器。
  run         从镜像创建并运行一个新容器。
  start       启动一个或多个已停止的容器。
  stats       实时显示容器资源使用情况的统计信息。
  stop        停止一个或多个正在运行的容器。
  top         显示容器的运行进程。
  unpause     取消暂停一个或多个容器内的所有进程。
  update      更新一个或多个容器的配置。
  wait        阻塞直到一个或多个容器停止,然后打印其退出代码。

Run 'docker container COMMAND --help' for more information on a command.

3.2 列出容器

docker ps 命令用于列出容器,它提供了多个选项来定制输出。

语法:

docker ps [OPTIONS]

别名(即等价命令):

docker container ls, docker container list, docker container ps, docker ps

参数说明:

Options:
  -a, --all             显示所有容器(默认只显示正在运行的容器)
  -f, --filter filter   基于提供的条件过滤输出。你可以根据容器的状态、名称、标签等过滤容器。
      --format string   使用自定义模板格式化输出:
                        'table':            Print output in table format with column headers (default)
                        'table TEMPLATE':   Print output in table format using the given Go template
                        'json':             Print in JSON format
                        'TEMPLATE':         Print output using the given Go template.
                        更多格式移步:https://docs.docker.com/go/formatting/ 
  -n, --last int        显示最后创建的 n 个容器(包括所有状态)。
  -l, --latest          显示最新创建的容器(包括所有状态)。这实际上是 -n=1 的快捷方式。
      --no-trunc        不截断输出。默认情况下,为了可读性,某些输出可能会被截断。
  -q, --quiet           仅显示容器 ID。这在你只需要容器 ID 列表时很有用。
  -s, --size            显示总文件大小。这包括容器的写层大小。

示例:

# 显示所有容器
docker ps -a
# 过滤容器,列出所有状态为 exited 的容器
docker ps -a -f status=exited
# 使用自定义格式,以 JSON 格式列出容器
docker ps --format json
# 使用自定义 Go 模板,只显示容器 ID 和名称:
docker ps --format "{{.ID}} {{.Names}}"
# 显示最后创建的 5 个容器
docker ps -n 5
# 仅显示容器 ID
docker ps -q
# 显示容器大小
docker ps -s

3.1 创建容器

docker run 命令是用于从镜像创建并启动一个新容器的 Docker 命令。它提供了丰富的选项来定制容器的运行环境和资源限制。

[root@localhost ~]# docker run --help

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Create and run a new container from an image

Aliases:
  docker container run, docker run

Options:
      --add-host list                    添加自定义的主机到 IP 的映射。这对于容器内部需要访问特定主机名的情况很有用。
      --annotation map                   Add an annotation to the container (passed through to the OCI runtime) (default map[])
  -a, --attach list                      附加到容器的标准输入(STDIN)、标准输出(STDOUT)或标准错误(STDERR)。这允许你与运行中的容器进行交互。
      --blkio-weight uint16              设置 Block IO 的相对权重,范围在 10 到 1000 之间,或者设置为 0 以禁用。这用于限制容器对磁盘 IO 的访问
      --blkio-weight-device list         Block IO weight (relative device weight) (default [])
      --cap-add list                     添加 Linux 功能, 这用于控制容器内的权限。
      --cap-drop list                    删除 Linux 功能
      --cgroup-parent string             为容器指定可选的父 cgroup。这用于资源管理和隔离。
      --cgroupns string                  指定 cgroup 命名空间的使用方式:
                                         'host':    在 Docker 主机的 cgroup 命名空间中运行容器
                                         'private': 在容器自己的私有 cgroup 命名空间中运行
                                         '':        Use the cgroup namespace as configured by the
                                                    default-cgroupns-mode option on the daemon (default)
      --cidfile string                   将容器 ID 写入指定的文件。这对于需要记录容器 ID 的脚本或自动化任务很有用。
      --cpu-period int                   设置 CPUCFS(完全公平调度器)的周期。这用于限制容器可以使用的 CPU 时间。
      --cpu-quota int                    设置 CPUCFS(完全公平调度器)的配额。
      --cpu-rt-period int                设置 CPU 实时周期的微秒数。这用于限制容器可以使用的实时 CPU 时间。
      --cpu-rt-runtime int               设置 CPU 实时运行时间的微秒数。
  -c, --cpu-shares int                   设置 CPU 共享权重。这是一个相对权重,用于在多个容器之间分配 CPU 资源。默认情况下,所有容器的权重都是 1024。权重越高的容器可以获得更多的 CPU 时间片。
      --cpus decimal                     限制容器可以使用的 CPU 数量。你可以指定一个小数来限制部分 CPU 资源,例如 1.5 表示容器可以使用一个半 CPU。
      --cpuset-cpus string               允许容器在指定的 CPU 上执行。你可以使用逗号分隔的列表或连字符指定的范围来指定 CPU。例如,0-3 表示容器可以在 CPU 0、1、2、3 上执行。
      --cpuset-mems string               允许容器在指定的内存节点上执行。这对于在多节点系统上运行的容器很有用。
  -d, --detach                           在后台运行容器,并打印容器 ID。这是启动长时间运行的服务或后台任务时的常用选项。
      --detach-keys string               覆盖用于分离容器的键序列。默认情况下,你可以使用 CTRL-P CTRL-Q 来分离容器,同时保持其运行。
      --device list                      将主机设备添加到容器中。这对于需要直接访问硬件设备的容器很有用,例如 GPU 或特定类型的存储设备。
      --device-cgroup-rule list          向 cgroup 允许的设备列表中添加一条规则。这用于控制容器对设备的访问权限。
      --device-read-bps list             限制容器对设备的读写速率。你可以指定设备的路径和速率限制(以字节/秒或 IO/秒为单位)。
      --device-read-iops list            Limit read rate (IO per second) from a device (default [])
      --device-write-bps list            Limit write rate (bytes per second) to a device (default [])
      --device-write-iops list           Limit write rate (IO per second) to a device (default [])
      --disable-content-trust            跳过镜像验证。默认情况下,如果启用了内容信任,Docker 将拒绝运行未签名的镜像。使用这个选项可以绕过这个限制,但可能会带来安全风险
      --dns list                         设置自定义 DNS 服务器。这对于需要解析特定域名或需要使用特定 DNS 服务器的容器很有用。
      --dns-option list                  设置 DNS 选项。这允许你指定额外的 DNS 配置,如 ndots(在查询完全限定域名之前需要多少个点)或 timeout(等待 DNS 响应的超时时间)。
      --dns-search list                  设置自定义 DNS 搜索域。这允许你指定在解析非完全限定域名时要搜索的域列表。
      --domainname string                设置容器的 NIS 域名。这对于需要在容器内部使用 NIS 服务的场景很有用。
      --entrypoint string                覆盖镜像的默认 ENTRYPOINT。这对于需要运行镜像中不同命令的场景很有用。
  -e, --env list                         设置环境变量。你可以使用此选项为容器设置环境变量,格式为 VAR_NAME=value。这对于配置应用程序非常有用。
      --env-file list                    从文件中读取环境变量。你可以指定一个包含环境变量定义的文件,Docker 将在启动容器时读取该文件并设置相应的环境变量。
      --expose list                      暴露一个端口或端口范围。此选项声明容器将监听哪些端口,但不会自动将这些端口映射到主机。通常与 -p 或 --publish 选项结合使用
      --gpus gpu-request                 向容器添加 GPU 设备。你可以指定要传递给容器的 GPU 数量或 'all' 以传递所有 GPU。这对于需要 GPU 加速的应用程序非常有用
      --group-add list                   向容器添加额外的用户组。这允许容器内的进程以指定的用户组身份运行。
      --health-cmd string                运行以检查健康状况的命令。你可以指定一个命令来定期检查容器的健康状况。如果命令退出状态码为非零,则容器被视为不健康
      --health-interval duration         运行检查之间的时间间隔。你可以指定时间间隔(毫秒、秒、分钟、小时)来控制健康检查的频率。
      --health-retries int               连续失败次数达到多少时报告不健康。如果健康检查命令连续失败指定次数,则容器被视为不健康。
      --health-start-interval duration   启动期间运行检查的时间间隔。在容器启动期间,你可以指定一个不同的时间间隔来控制健康检查的频率。
      --health-start-period duration     容器初始化开始前的启动期。在启动期结束之前,健康检查失败不会计入连续失败次数。
      --health-timeout duration          允许单个检查运行的最大时间。你可以指定时间限制(毫秒、秒、分钟、小时)来控制健康检查命令的运行时间
      --help                             打印用法信息。此选项将显示 docker run 命令的完整用法和所有可用选项
  -h, --hostname string                  设置容器的主机名。这允许你为容器指定一个唯一的主机名,这在容器间通信时非常有用。
      --init                             在容器内运行一个 init 进程。init 进程负责转发信号和回收进程,这有助于提高容器的稳定性和安全性。
  -i, --interactive                      即使未附加也保持 STDIN 打开。此选项允许你与容器中的进程进行交互,即使你没有通过 docker attach 命令附加到容器
      --ip string                        设置容器的 IPv4 地址。你可以指定一个静态 IP 地址供容器使用。
      --ip6 string                       设置容器的 IPv6 地址。与 --ip 选项类似,但用于 IPv6 地址。
      --ipc string                       设置 IPC 模式。IPC(进程间通信)模式决定了容器如何与其他容器或主机进行进程间通信。
      --isolation string                 设置容器隔离技术。你可以指定使用哪种隔离技术(如 default、process、hyperv)来运行容器。
      --kernel-memory bytes              设置内核内存限制。你可以指定容器可以使用的内核内存量(以字节为单位)
  -l, --label list                       为容器设置元数据标签。标签以键值对的形式存在,有助于组织和筛选容器。
      --label-file list                  从一个包含标签定义的文件中读取标签。文件应包含一行一个的键值对。
      --link list                        添加到另一个容器的链接。此选项允许容器间安全通信,但 Docker 官方推荐使用网络和卷来替代。
      --link-local-ip list               设置容器的IPv4/IPv6链路本地地址。这些地址用于容器间的直接通信。
      --log-driver string                为容器指定日志驱动程序。Docker 支持多种日志驱动程序,如 json-file、syslog 等。
      --log-opt list                     为日志驱动程序设置选项。这些选项依赖于所选的日志驱动程序。
      --mac-address string               为容器指定MAC地址。这有助于在需要固定网络配置的场景中
  -m, --memory bytes                     设置容器的内存限制。可以指定为字节数或带有单位的字符串(如 512m)
      --memory-reservation bytes         设置容器的内存软限制。如果系统内存紧张,Docker 将尝试保持容器内存使用量低于此限制。
      --memory-swap bytes                设置容器的交换内存限制。可以设置为 -1 以启用无限交换。
      --memory-swappiness int            调整容器的内存交换倾向。值范围为 0 到 100,默认为 -1(由 Docker 守护进程决定)。
      --mount mount                      将文件系统挂载到容器。这是 --volume 的更现代替代品,提供了更灵活的挂载选项。
      --name string                      为容器指定名称。这有助于轻松识别和引用容器。
      --network network                  将容器连接到指定的网络。Docker 支持自定义网络,允许容器间复杂的通信模式。
      --network-alias list               为容器在网络作用域内添加别名。这有助于简化容器间的通信。
      --no-healthcheck                   禁用容器指定的任何健康检查。如果容器镜像包含健康检查指令,此选项将覆盖它。
      --oom-kill-disable                 禁用 OOM(内存不足)杀手。在内存不足的情况下,Docker 通常会自动杀死占用过多内存的容器进程。使用此选项可以禁用此行为,但可能导致系统不稳定。
      --oom-score-adj int                调整主机的 OOM 偏好设置。值范围为 -1000 到 1000,影响 Docker 容器在内存不足时被杀死的优先级。
      --pid string                       设置要使用的 PID 命名空间。这允许容器共享或隔离进程 ID。
      --pids-limit int                   调整容器的 PID 限制。设置为 -1 表示无限制。
      --platform string                  如果服务器支持多平台,则设置平台。这允许在不同架构上运行容器。
      --privileged                       给予容器扩展权限。这允许容器执行许多通常被限制的操作,如加载内核模块。
  -p, --publish list                     将容器的端口发布到主机。格式通常为 宿主机端口:容器端口。
  -P, --publish-all                      将容器暴露的所有端口随机发布到主机的端口上。
      --pull string                      在运行之前拉取镜像。选项包括 "always"(始终拉取)、"missing"(仅当镜像不存在时拉取)和 "never"(从不拉取)。
  -q, --quiet                            抑制拉取镜像时的输出。这个选项可以让 Docker 在拉取镜像时保持安静,不显示进度条或下载信息。
      --read-only                        以只读方式挂载容器的根文件系统。这可以增强容器的安全性,防止对文件系统的意外修改。
      --restart string                   设置容器退出时的重启策略。可选值包括 "no"(不重启)、"on-failure"(失败时重启)、"always"(总是重启)等。默认值为 "no"--rm                               容器退出时自动移除。这个选项可以让 Docker 在容器停止后自动删除它,避免留下无用的容器实例。
      --runtime string                   为容器指定运行时。Docker 支持多种运行时,如 runc(默认)、kata-containers 等。
      --security-opt list                设置安全选项。这些选项允许你调整容器的安全策略,如 SELinux 标签、AppArmor 配置等。
      --shm-size bytes                   设置 /dev/shm 的大小。/dev/shm 是一个临时文件系统,用于存储共享内存段。
      --sig-proxy                        代理接收到的信号给进程。默认情况下,Docker 会将发送给容器的信号代理给容器内的主进程。设置为 false 可以禁用此行为。
      --stop-signal string               设置停止容器的信号。默认值是 SIGTERM,但你可以指定其他信号,如 SIGKILL。
      --stop-timeout int                 设置停止容器的超时时间(以秒为单位)。如果容器在指定时间内没有停止,Docker 将强制终止它。
      --storage-opt list                 设置存储驱动选项。这些选项允许你调整存储驱动的行为,如文件系统的挂载选项。
      --sysctl map                       设置 sysctl 选项。这些选项允许你调整内核参数,如网络配置、内存管理等。
      --tmpfs list                       挂载一个 tmpfs 目录。tmpfs 是一种基于内存的文件系统,可以用于存储临时数据。
  -t, --tty                              分配一个伪终端(pseudo-TTY)。这个选项可以让容器在运行时分配一个伪终端,使得你可以像使用本地终端一样与容器进行交互。
      --ulimit ulimit                    设置 ulimit 选项。ulimit 用于控制 shell 进程及其子进程可以使用的资源量,如内存、CPU 时间等。
  -u, --user string                      设置容器内运行进程的用户名或用户 ID。你还可以指定用户所属的组名或组 ID,格式为 <name|uid>[:<group|gid>]--userns string                    指定要使用的用户命名空间。用户命名空间是一种内核功能,它允许你将容器内的用户和组 ID 映射到主机上的不同用户和组 ID。
      --uts string                       指定要使用的 UTS 命名空间。UTS 命名空间包含主机名和域名信息,允许你为每个容器设置独立的主机名和域名。
  -v, --volume list                      绑定挂载一个卷。这个选项允许你将主机上的目录或文件挂载到容器内的指定位置,实现数据的持久化和共享。
      --volume-driver string             为容器指定可选的卷驱动程序。Docker 支持多种卷驱动程序,如 local(默认)、ceph、cifs 等,允许你根据需求选择适合的存储后端
      --volumes-from list                从指定的容器挂载卷。这个选项允许你从一个或多个已运行的容器中挂载卷,实现容器间的数据共享。
  -w, --workdir string                   设置容器内的工作目录。这个选项允许你指定容器启动时的工作目录,即容器内进程的当前工作目录。

四、镜像

在这里插入图片描述

1、UnionFS(联合文件系统)

联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来只能看到一个文件系统。联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

2、镜像加载原理

Docker的镜像实际由一层一层的文件系统组成:

  • bootfs(boot file system)主要包含bootloader和kernel。bootloader主要是引导加载kernel,完成后整个内核就都在内存中了。此时内存的使用权已由bootfs转交给内核,系统卸载bootfs。可以被不同的Linux发行版公用。
  • rootfs(root file system),包含典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同操作系统发行版(Ubuntu,Centos等)。因为底层直接用Host的kernel,rootfs只包含最基本的命令,工具和程序就可以了。

3、分层理解

所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的容器层。

容器在启动时会在镜像最外层上建立一层可读写的容器层(R/W),而镜像层是只读的(R/O)。
在这里插入图片描述

# 编辑容器后提交容器成为一个新镜像
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[tag]  

五、容器数据卷

为了实现数据持久化,使容器之间可以共享数据。可以将容器内的目录,挂载到宿主机上或其他容器内,实现同步和共享的操作。即使将容器删除,挂载到本地的数据卷也不会丢失。

1、具名挂载

docker run -d  -v 卷名:容器内目录  镜像名/id

通过docker volume inspect 卷名 命令找到主机内目录

所有docker容器内的卷,在未指定主机内目录时,都在:/var/lib/docker/volumes/卷名/_data 下

2、匿名挂载

docker run -d  -v 容器内目录  镜像名/id  

匿名挂载后,使用docker volume ls命令查看所有挂载的卷

3、绑定挂载

dokcer run -it -v 主机内目录:容器内目录 镜像名/id

将容器内目录挂载到主机内目录上,通过docker inspect命令查看该容器即可以看到挂载信息

4、容器挂载到另一个容器数据卷上

将两个容器进行挂载:

docker run -it --name container02 --volumes from container01 镜像名/id   

六、Dockerfile

Dockerfile是用来构建docker镜像的文件

构建步骤:编写一个dockerfile文件,随后运行以下命令:

docker build -f 文件路径 -t 标签 .  # 文件名为Dockerfile时可省略且最后的.不要忽略
docker run     # 运行镜像
docker push    # 发布镜

Dockerfile命令:

dockerfile命令#

命令效果
FROM基础镜像:Centos/Ubuntu
MAINTAINER镜像作者+邮箱
RUN镜像构建的时候需要运行的命令
ADD为镜像添加内容(压缩包)
WORKDIR镜像工作目录(进入容器时的目录)
VOLUME挂载的目录
EXPOSE暴露端口配置
CMD/ENTRYPOINT指定这个容器启动时要运行的命令(CMD替代先前命令,ENTRYPOINT在先前命令后追加)
COPY类似于ADD,将文件拷贝到镜像中
ENV构建时设置环境变量

七、Docker网络原理

1、Docker 启动后的系统情况

  • 创建了 docker0 网桥并分配了 IP 地址
    [root@localhost ~]# ip addr | grep docker0
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
    
    Docker Daemon 首次启动时会创建一个虚拟网桥,默认的名称是 docker0,然后按照 RPC1918 的模型在私有网络空间中给这个网桥分配一个子网。Docker Daemon 会在几个备选地址段里给 docker0 选一个地址,通常是以 172 开头的一个地址。
  • Linux 的 ip_forward ( IPv4 的 IP 转发功能)开启
    [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward
    1
    
  • 添加了 iptables 规则
    [root@localhost ~]# iptables-save | grep docker0
    -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
    -A DOCKER -i docker0 -j RETURN
    -A POSTROUTING_ZONES -o docker0 -g POST_docker
    -A PREROUTING_ZONES -i docker0 -g PRE_docker
    -A PREROUTING_ZONES -i docker0 -g PRE_docker
    -A PREROUTING_ZONES -i docker0 -g PRE_docker
    -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    -A FORWARD -o docker0 -j DOCKER
    -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
    -A FORWARD -i docker0 -o docker0 -j ACCEPT
    -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
    -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
    -A FORWARD_IN_ZONES -i docker0 -g FWDI_docker
    -A FORWARD_OUT_ZONES -o docker0 -g FWDO_docker
    -A INPUT_ZONES -i docker0 -g IN_docker
    
    这些规则定义了数据包如何通过 docker0 网桥进行转发和处理。
    • -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE:对于源IP地址在172.17.0.0/16子网内的数据包,如果它们不是从docker0接口发出的,则对它们进行源地址伪装(MASQUERADE)。这通常用于NAT(网络地址转换),使得Docker容器能够访问外部网络。
    • -A DOCKER -i docker0 -j RETURN:如果数据包是从docker0接口进入的,则直接返回,不进行后续处理。这通常是为了避免对Docker容器内部通信的不必要干扰。
    • POSTROUTING_ZONES和PREROUTING_ZONES链规则:这些规则涉及到iptables的区域(zones)概念,用于处理来自或发往特定网络接口的数据包。与docker0相关的规则将数据包引导到特定的用户自定义链(如POST_docker、PRE_docker)进行处理。
    • -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT:这条规则允许已建立连接或相关的数据包从其他接口转发到docker0接口。
    • -A FORWARD -o docker0 -j DOCKER:这条规则将发往docker0接口的数据包引导到DOCKER链进行处理。
    • -A FORWARD -i docker0 ! -o docker0 -j ACCEPT:这条规则允许从docker0接口进入且不从docker0接口出去的数据包被接受。这通常用于允许Docker容器访问外部网络。
    • -A FORWARD -i docker0 -o docker0 -j ACCEPT
      这条规则允许在docker0接口之间循环的数据包被接受。虽然这种情况在实际应用中较少见,但它确保了规则的全面性。
    • DOCKER-ISOLATION-STAGE链规则:这些规则用于实现Docker容器之间的隔离。
    • -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2:如果数据包是从docker0接口进入且不从docker0接口出去,则将其引导到DOCKER-ISOLATION-STAGE-2链进行处理。
    • -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP则表示,如果数据包试图从docker0接口出去(在隔离阶段被检测到),则将其丢弃。
    • FORWARD_IN_ZONES和FORWARD_OUT_ZONES链规则:这些规则同样涉及到iptables的区域概念,用于处理进入或离开特定网络接口区域的数据包。与docker0相关的规则将数据包引导到特定的用户自定义链(如FWDI_docker、FWDO_docker)进行处理。
    • -A INPUT_ZONES -i docker0 -g IN_docker:将进入docker0接口的数据包引导到IN_docker链进行处理。这通常用于对进入Docker容器的数据包进行额外的安全检查或处理。

2、Docker 的网络模式

标准的 Docker 支持 4 种网络模式,可以在使用 docker run 命令启动容器的时候通过 --net 参数指定容器的网络模式:

  • bridge-net=bridge,Docker 默认的网络模式,新建的容器将拥有独立的网络命名空间,并连接到 Docker 的网桥 docker0 中。
  • container--net=container:NAME_or_ID,新建的容器将与指定容器使用同一个网络命名空间,共享网络栈,可以直接通过 lo 环回接口进行通信,但其他资源还是相互隔离的。
  • host--net=host,新建的容器将与宿主机使用同一个网络命名空间,但其他资源还是隔离的。容器进程可以跟主机其它 root 进程一样打开低范围的端口,如果进一步的使用 --privileged=true,容器会被允许直接配置主机的网络堆栈。
  • none--net=none,新建的容器将拥有独立的网络命名空间,但不进行网络配置,后续需要手动配置。

默认的 Docker 网络模型提供了一个IP 地址段是 172.17.0.0/16 的 docker0 网桥。每个容器都会在这个子网内获得 IP 地址,并且将 docker0 网桥的IP 地址(172.17.42.1)作为其默认网关。需要注意的是,Docker宿主机外面的网络不需要知道任何关于这个172.17.0.0/16 的信息或者知道如何连接到其内部,因为 Docker 的宿主机针对容器发出的数据,在物理网卡地址后面都做了IP伪装 MASQUERADE(隐含 NAT)。也就是说,在网络上看到的任何容器数据流都来源于该 Docker 节点的物理 P 地址。这里所说的网络都指连接这些主机的物理网络。

2.1 bridge 模式

在 bridge 模式下,针对由 Docker 建的每一个容器,都会创建一个虚拟以太网设备 —— Veth 设备对,其中一端关联到网桥 docker0 上,另一端使用 Linux 的网络命名空间技术映射到容器内的 eth0 设备,然后在网桥的地址段内给 eth0 接口分配一个没有使用过的 IP 地址。

Docker 的 bridge 模式的网络模型如下:

在这里插入图片描述

docker0 地址段默认情况下在宿主机外部是不可见的,所以在同一台机器内的容器之间可以相互通信,不同主机上的容器不能相互通信,实际上它们甚至有可能在相同的网络地址范围内(不同主机上的 docker0 地址段可能是一样的)。

为了让它们跨节点相互通信,就必须在主机的地址上分配端口,然后通过这个端口将网络流量路由或代理到目标容器上。这样做显然意味着一定要在容器之间小心谨慎地协调好端口的分配情况,或者使用动态端口的分配技术,而这二者都是困难且会增加复杂度的事情。这都是 Docker 的网络模型在跨主机访问时面临的问题。

# 1、创建一个 Docker 容器,将容器8080端口映射到主机的4000
[root@localhost ~]# docker run -d -p 8080:4000 --name test tomcat
032de77f49edd74a64c519528d7ce6f0fa61173480498e67fff0a1abc4465730

# 2、查看容器网络模式
[root@localhost ~]# docker inspect 032de77f49ed | grep NetworkMode
            "NetworkMode": "bridge",
[root@localhost ~]# docker network inspect bridge | grep EndpointID
                "EndpointID": "412cb620715af67a104b8ff208bfe11bbbac19cc3fe9b3331402c8a6d1457309",

# 3、查看网桥连接与容器路由
# 宿主机上的 Veth 设备对已经建立,连接容器与网桥 docker0。
[root@localhost ~]# ip addr | grep veth
5: veth61a051f@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
# 容器内默认停止的回环设备 lo 被启动,外面宿主机连接进来的 Veth 设备也被命名成了 eth0, 并且已经配置了地址 172.17.0 2。
# 如果容器不支持ip命令,可使用 `sudo nsenter -t $(docker inspect --format '{{ .State.Pid }}' 容器ID或名称 ) -n ip addr show` 来获取网络接口信息,当然也可以给容器安装对应的软件包(iptoute2)来支持ip命令
[root@localhost ~]# docker exec -it test ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:1c:e3:3e brd ff:ff:ff:ff:ff:ff
	inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
	   valid_lft forever preferred_lft forever
# 容器内路由信息表包含一条到 docker0 的子网路由和一条到 docker0 的默认路由。
# 第一条路由为默认路由,意味着容器内所有不匹配任何其他路由规则的网络流量都将通过网关172.17.0.1发送出去。eth0 是容器内的默认网络接口名称。172.17.0.1通常是Docker桥接网络(如docker0桥接网络)的默认网关地址。
# 第二条路由规则指定了目的网络 172.17.0.0/16 的流量应该通过 eth0 接口发送。proto kernel 表示这条路由是由内核自动创建的。scope link 表示这条路由仅适用于直接连接的网络。src 172.17.0.2 表明发送出去的流量将使用 172.17.0.2 作为源 IP 地址。
[root@localhost ~]# docker exec -it test ip route
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2 

# 4、查看 iptables 规则
# 请求宿主机 8080 端口的数据包目的地址将被转换为容器的服务地址 172.17.0.2:4000。
# 第一条规则将原地址和目的地址为容器IP 172.17.0.2/32,MASQUERADE动态地转换为可用的宿主机IP地址。
# 第二条规则用于将宿主机的 8080 端口映射到容器 172.17.0.2 的 4000 端口上。
# 第三条规则允许特定的容器内部通信通过 docker0 桥接网络
[root@localhost ~]# iptables-save | grep 4000
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 4000 -j MASQUERADE
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:4000
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 4000 -j ACCEPT

2.2 container 网络模式

使用 container 网络模式创建的容器将与指定容器使用同一个网络命名空间,共享网络栈,可以直接通过 lo 环回接口进行通信,但其他资源还是相互隔离的。

# 1、使用 container 网络模式创建一个容器
[root@localhost ~]# docker run -d --net=container:test --name test2 nginx
574815fdf6e8e29e6cd14ba599f53e0123c3db6735717c6554cab80a830ad49c

# 2、查看容器网络模式
[root@localhost ~]# docker inspect test2 | grep NetworkMode
            "NetworkMode": "container:032de77f49edd74a64c519528d7ce6f0fa61173480498e67fff0a1abc4465730",

# 3、查看容器网络
# 可以看到,container 模式的容器与指定容器处于同一网络命名空间,使用同一个 ip,两个容器之间可通过 lo 设备通信,使用端口不可重复。
# container 网络模式的容器无法进行端口映射。
[root@localhost ~]# sudo nsenter -t $(docker inspect --format '{{ .State.Pid }}' test2) -n ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

2.3 host 网络模式

使用 host 网络模式创建的容器将与宿主机使用同一个网络命名空间,但其他资源还是隔离的。容器进程可以跟主机其它 root 进程一样打开低范围的端口,如果进一步的使用 --privileged=true,容器会被允许直接配置主机的网络堆栈。

# 1、使用 host 网络模式创建一个容器
[root@localhost ~]# docker run -d --net=host --name test3 nginx
b281ffed1ecdeae3acece7570e884c9e2024889448da7fe1d67219d80d43b668

# 2、查看容器网络模式
[root@localhost ~]# docker inspect test3 | grep NetworkMode
            "NetworkMode": "host",

# 3、查看容器网络
# 容器与宿主机使用同一网络命名空间,在容器中可以看到 docker0 网桥。
[root@localhost ~]# sudo nsenter -t $(docker inspect --format '{{ .State.Pid }}' test3) -n ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:1c:e3:3e brd ff:ff:ff:ff:ff:ff
    inet 10.100.110.111/24 brd 10.100.110.255 scope global noprefixroute dynamic ens160
       valid_lft 1535sec preferred_lft 1535sec
    inet6 wwww::www:www:www:www/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ab:06:0d:13 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 ww::ww:ww:ww:ww/64 scope link 
       valid_lft forever preferred_lft forever
5: veth61a051f@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 16:17:1f:1f:11:8c brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 ee::ee:ee:ee:ee/64 scope link 
       valid_lft forever preferred_lft forever

# 4、查看宿主机端口占用
# 容器直接占用宿主机的端口。
[root@localhost ~]# ss -tnl | grep 80
LISTEN     0      511          *:80                       *:*                  
LISTEN     0      4096         *:8080                     *:*                  
LISTEN     0      511       [::]:80                    [::]:*                  
LISTEN     0      4096      [::]:8080                  [::]:* 

2.4 none 网络模式

使用 none 网络模式创建的容器将拥有独立的网络命名空间,但不进行网络配置,后续需要手动配置。

# 1、使用 none 网络模式创建一个容器
[root@localhost ~]# docker run -d --net=none --name test4 nginx
7c2564ffc43f3a5f47257b467c384f282684b7fa477f4cc7f2feea7afe23fca8

# 2、查看容器网络模式
[root@localhost ~]# docker inspect test4 | grep NetworkMode
            "NetworkMode": "none",

# 3、查看容器网络
# 只有 lo 设备,暂无 veth 设备,未设置 ip。
[root@localhost ~]# sudo nsenter -t $(docker inspect --format '{{ .State.Pid }}' test4) -n ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

2.5 自定义网络

创建自定义网络时,Docker会在该网络上启动一个嵌入式的DNS服务器。这个DNS服务器专门用于解析同一网络中的容器名和服务名。

自定义网络中的DNS服务器能够动态地更新和维护容器名的解析记录,从而确保容器之间可以通过名称进行通信。

# 1、创建自定义网络
# 如果没有指定子网和子网掩码,Docker会自动选择一个默认的子网和子网掩码
# docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1 my_custom_network
docker network create --driver bridge my_custom_network
# 查看网络列表
docker network ls
# 查看网络详细信息,包括容器连接情况、网络配置等。
docker network inspect my_custom_network

# 2、运行容器并连接到自定义网络
docker run -d --name container1 --network my_custom_network nginx
docker run -d --name container2 --network my_custom_network nginx

# 3、测试容器名通信
docker exec -it container1 ping container2

2.6 使用--link 连接容器

在Docker的世界里,--link 参数曾经是用来连接两个容器,使得它们之间可以方便地通信。不过,需要注意的是,随着Docker的发展,--link 参数已经被视为一种较旧且不太推荐的方式,因为它有一些局限性,比如它创建的连接是单向的,而且在多宿主机或Swarm模式下不太适用。现代Docker更推荐使用Docker网络(networks)来实现容器间的通信。

docker run --name myapp --link db:mysql -d myappimage

2.7 删除测试数据

# 停止所有容器
docker stop $(docker ps -aq)

# 删除所有容器
docker rm $(docker ps -aq)

# 删除所有镜像
docker rmi $(docker images -q)

# 删除自定义网络
docker network rm my_custom_network 

3、容器通信

3.1 通过IP地址通信

在bridge模式下,容器拥有独立的IP地址和Network Namespace,但共享同一个子网。这实现了网络隔离和互操作性。然而,这也意味着容器之间的通信需要通过Docker的虚拟网桥进行转发。

步骤:

  • 启动两个容器,确保它们都在bridge网络上(这通常是默认的,除非你指定了其他网络)。
  • 使用docker inspect命令查看容器的IP地址。
  • 在一个容器中使用ping或其他网络工具测试与另一个容器的连通性。

优点:

  • 简单直接,无需额外的配置。

缺点:

  • 需要记住容器的IP地址,这在动态环境中可能不太方便。

3.2 通过容器名通信

Docker 提供了一个DNS解析服务,允许容器通过容器名进行通信。在bridge模式下,只要容器连接在同一个自定义网络上,它们就可以通过容器名称来访问其他容器,而无需知道对方的IP地址。

步骤:

  • 创建一个自定义的bridge网络。
  • 启动两个容器,并将它们连接到刚才创建的自定义网络上。
  • 在一个容器中使用容器名来访问另一个容器的服务(例如,通过http://container_name访问Web服务)。

优点:

  • 更加灵活和方便,因为无需记住容器的IP地址。
  • 容器名通常比IP地址更具可读性。

缺点:

  • 依赖于Docker的DNS服务,如果DNS服务出现问题,可能会影响通信。

二十、资料

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。