随笔 - 134,  文章 - 0,  评论 - 0,  阅读 - 21280

Docker

https://www.processon.com

docker

[root@iZuf6b2qg1ny365ykqvfc0Z ~]# docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:20:16 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:23:58 2018
  OS/Arch:      linux/amd64
  Experimental: false
[root@iZuf6b2qg1ny365ykqvfc0Z ~]# docker info
Containers: 2
 Running: 2
 Paused: 0
 Stopped: 0
Images: 3
Server Version: 18.03.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 773c489c9c1b21a6d78b5c538cd395416ec50f88
runc version: 4fc53a81fb7c994640722ac585fa9ca548971871
init version: 949e6fa
Security Options:
 seccomp
  Profile: default
Kernel Version: 3.10.0-1062.18.1.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 1.795GiB
Name: iZuf6b2qg1ny365ykqvfc0Z
ID: SKYU:HP4P:3NVM:3P7Z:76PH:SRGM:QKN6:RI2G:SSBD:P5UM:EUNG:45PU
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

安装

一、配置要求

系统:Centos7
Linux 内核:官方建议 3.10 以上

注意:本文的命令使用的是 root 用户登录执行,不是 root 的话所有命令前面要加 sudo

1.查看当前的内核版本

uname -r
[root@hjz ~]# cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

2.更新 yum 包(使用 root 权限,生产环境中此步操作需慎重)

yum -y update

yum -y update 升级所有包同时也升级软件和系统内核;

yum -y upgrade 只升级所有包,不升级软件和系统内核

3.卸载旧版本(如果之前安装过的话)

yum remove docker  docker-common docker-selinux docker-engine

二、安装Docker

1.安装软件包

安装需要的软件包,yum-util 提供yum-config-manager功能,另两个是devicemapper驱动依赖

yum install -y yum-utils device-mapper-persistent-data lvm2

2.设置 yum 源

yum-config-manager --add-repo http://download.docker.com/linux/centos/docker-ce.repo(中央仓库)

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo(阿里仓库)

3.选择docker版本

查看可用版本有哪些

yum list docker-ce --showduplicates | sort -r

4.安装docker

ee 企业版 ce 社区版

选择一个版本并安装:yum install docker-ce-版本号

yum -y install docker-ce-18.03.1.ce

5.启动 Docker

启动docker前准备*

(docker应用需要用到各种端口,逐一设置比较麻烦,建议直接关闭防火墙) 重要的事请说三遍:启动docker前,一定要关闭防火墙、启动docker前,一定要关闭防火墙、启动docker前,一定要关闭防火墙(关闭前可通过查看查看防火墙状态来检验是否关闭)

#关闭
systemctl stop firewalld
#禁止开机启动防火墙
systemctl disable firewalld
systemctl start docker
systemctl enable docker  设置开机自启
#查看是否启动成功有多种方法
systemctl status docker

6.查看docker版本

[root@hjz ~]# docker version
Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:20:16 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:23:58 2018
  OS/Arch:      linux/amd64
  Experimental: false

卸载docker

1.卸载依赖

yum remove docker-ce docker-ce-cli containerd.io

2.删除资源

rm -rf /var/lib/docker

三.安装dockerCompose

sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

https://www.docker.com/

为什么使用容器?

1.上线流程繁琐

开发->测试->申请资源->审批->部署->测试等环节

2.资源的利用效率低

普遍服务器利用率低,造成过多的浪费

3.扩容/缩容不及时

以为高峰期扩容流程繁琐,上线不及时

4.服务器环境臃肿

服务器越来越臃肿,对维护和迁移带来困难

5.环境不一致

构建--运输--运行

底层原理

Docker是这样工作的?

Docker是一个Clinent-Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!DockerServer接收到Docker-Client的指令,就会执行这个指令

Docker为什么比VM快?

1.Docker有着比虚拟机更少的抽象层
2.利用的宿主机的内核,vm需要的是Guest OS.

介绍

  • 使用最广泛的开源容器引擎
  • 一种操作系统级的虚拟化技术
  • 依赖于Linux内核特性,Namespace(资源隔离)和Cgroups(资源限制)
  • 一个简单的应用程序打包工具

自 2013 年开放源代码发布以来,Docker 成为一项最受欢迎的技术之一。许多公司都在为此做出贡献,并且大量的人正在使用和采用它。但是为什么如此受欢迎?它提供了以前没有的功能?在此博客文章中,我们想更深入地研究 Docker 内部,以了解其工作原理。

这篇文章的第一部分将简要介绍基本的架构概念。在第二部分中,我们将介绍四个主要功能,这些功能构成了 Docker 容器中隔离的基础:1. 用户组,2. 命名空间,3. 可堆叠的图像层和写时复制,4. 虚拟网络桥。在第三部分中,将讨论使用容器和 Docker 时的机遇与挑战。最后,我们回答一些有关 Docker 的常见问题。

设计目标

  • 提供简单的应用程序打包工具
  • 开发人员和运维人员职责逻辑分离
  • 多环境保持一致性

镜像和容器

Image镜像

  • Docker image 是一个read-only文件
  • 这个文件包含文件系统,源码,库文件,依赖,工具等一些运行application所需要的文件
  • 可以理解成一个模版
  • docker image具有分层的概念

Container容器

  • 一个运行中的docker image文件
  • 实质是复制image并在image最上层加上一层read-write的层(称为container layer容器层)
  • 基于同一个image可以创建多个container

容器vs虚拟机

docker

虚拟机:

  • 底层计算机硬件--Computer Hardware
  • 速度机 ----Host OS
  • Hypervisor--虚拟化的核心 模拟多个虚拟机所具备的CPU\网络 ---资源调度
  • Guest OS 一个独立的操作系统
  • APP运行在对应OS层上的应用程序

docker:

  • Docker Engine

性能对比

Container(联合文件系统) VM
启动速度 秒级 分钟级
运行性能 接近原生(操作系统级别的虚拟化)--只是在进程层面-进程隔离(逻辑) 5%损耗
磁盘占用 MB GB
数量 成百上千 一般几十台
隔离性 进程级 系统级(更彻底)
封装程度 只打包项目代码和依赖关系,共享宿主机内核 完整的操作系统

容器:

1.容器提供一个基本的独立环境,实现容器隔离、资源限制

2.主要解决应用层面问题,应用快速部署、高效管理

虚拟机:

1.提升服务器资源利用率

2.提供一个完全隔离的环境

基本架构

"Docker 是一个开源项目,可以自动在软件容器内部署应用程序。"- 维基百科

人们在谈论操作系统级虚拟化时通常会引用容器。操作系统级虚拟化是一种方法,其中操作系统的内核允许存在多个隔离的应用程序实例。有许多可用的容器实现,其中之一是 Docker。

Docker 根据镜像定义了在创建容器时应在容器中放置的内容。定义镜像是通过 Dockerfile 文件来实现的。Dockerfile 文件包含有关如何逐步构建映像的说明(不要担心,稍后您将了解有关内部正在进行的操作的更多信息)。例如,以下 Dockerfile 将从包含 OpenJDK 的映像开始,在其中安装 Python 3, 复制镜像中的requirements.txt文件,然后安装改文件需求的所有 Python 软件包。

FROM openjdk:8u212-jdk-slim

RUN apt-get update \

  && apt-get install -y --no-install-recommends \

    Python3=3.5.3-1 \

    Python3-pip=9.0.1-2+deb9u1 \

  && rm -rf /var/lib/apt/lists/*

COPY requirements.txt requirements.txt

RUN pip3 install --upgrade -r requirements.txt

映像通常存储在称为 Docker registries 的映像存储库中。Dockerhub 是公共 Docker 注册中心。为了下载映像并启动容器,您需要拥有 Docker 主机。Docker 主机是一台运行 Docker 守护程序的 Linux 机器(守护程序是一个始终在运行,等待工作完成的后台进程)。

为了启动容器,您可以使用 Docker 客户端,该客户端将必要的指令提交给 Docker 守护程序。如果 Docker 守护程序无法在本地找到所请求的映像,它也正在与 Docker 注册表进行对话。下图说明了 Docker 的基本架构 :

docker architecture

需要注意的一点是,Docker 本身并不提供实际的容器化,仅使用 Linux 中可用的容器化。接下来让我们深入了解下其中的技术细节。

镜像(image):

docker镜像就好比一个模版,可以通过这个模版来创建容器服务,xxx镜像----》run---》xxx容器(提供服务器),通过这个镜像可以创建多个容器(最终服务网运行或者项目运行就是在容器中的)

容器(container):

Docker利用容器技术,独立运行一个或者组应用,通过镜像来创建的

启动、停止、删除、基本命令!

目前就可以把这个容器理解为就是一个简易的linux系统

仓库(repository):

仓库就是存放镜像的地方

容器隔离

Docker 通过四个主要概念的组合来实现不同容器的隔离:1)cgroups,2)namespaces,3)stackableimage layers 和 copy on write,4)virtual network bridges。在下面的小节中,我们将详细解释这些概念。

控制组 (Cgroups)

Linux 操作系统管理可用的硬件资源 (内存、CPU、磁盘 I/O、网络 I/O,…),并为进程访问和利用它们提供一种方便的方式。例如,Linux 的 CPU 调度程序会注意每个线程最终都会在 CPU 核心上获得一些时间,这样就不会有应用程序被困在等待 CPU 时间。

控制组 (cgroup) 是一种将资源子集分配给特定进程组的方法。这可以用来,例如,确保即使你的 CPU 忙于 Python 脚本,你的 PostgreSQL 数据库仍然有专用的 CPU 和 RAM。下图在一个 4 个 CPU 核和 16 GB RAM 的示例场景中说明了这一点。

cgroups

在 Zeppelin 中启动的所有 zeppelin-grp 笔记本将仅使用 Core1 和 Core2,而 PostgreSQL 进程共享 Core3 和 Core4。这同样适用于内存。cGroup 是容器隔离中的一个重要构建块,因为它们允许硬件资源隔离

命名空间

当 cgroups 隔离硬件资源时,命名空间会隔离和虚拟化系统资源。可以虚拟化的系统资源包括进程 ID 、主机名、用户 ID 、网络访问、进程间通信和文件系统。让我们首先深入到一个进程 ID (PID) 命名空间的例子,以使这一点更清楚,然后简要讨论其他命名空间。

PID 命名空间

Linux 操作系统将进程组织在所谓的进程树中。树根是操作系统启动后运行的第一个进程,它的 PID 为 1 。 由于只能存在一个进程树,所有其它的进程 (例如:火狐,终端模拟器, SSH 服务器等等) 需要(直接或间接)由根进程启动。由于根进程初始化了所有其它进程,所以它通常被称为 init 进程。

下图说明了典型进程树的部分功能,其中 init 进程启动了日志服务 ( syslogd )、调度程序 ( cron ) 以及登录 shell ( bash ):

1 /sbin/init

+-- 196 /usr/sbin/syslogd -s

+-- 354 /usr/sbin/cron -s

+-- 391 login

    +-- 400 bash

        +-- 701 /usr/local/bin/pstree

在进程树内,每个进程都可以看到其他进程,如果他们愿意的话,进程之间可以互发信号 (例如,请求进程停止)。 使用 PID 命名空间虚拟化特定进程及其所有子进程的 PID ,使其认为它有 PID 1 。 之后它将无法看到除自己的子进程之外的其他进程。下图说明了不同的 PID 命名空间是如何隔离两个 Zeppelin 进程的子进程树。

1 /sbin/init

|

- ...
  |
  +-- 506 /usr/local/zeppelin
    1 /usr/local/zeppelin
    +-- 2 interpreter.sh
    +-- 3 interpreter.sh
  +-- 511 /usr/local/zeppelin
    1 /usr/local/zeppelin
    +-- 2 java

文件系统命名空间

命名空间的另一个用例是 Linux 文件系统。类似于 PID 命名空间,文件系统命名空间虚拟化和隔离树的部分 - 在这种情况下即文件系统树。 Linux 文件系统被组织为一棵树的形式,它有一个树根,通常指 /

为了在文件系统级别上实现隔离,命名空间将文件系统树中的节点映射到该命名空间内的虚拟根目录。在这个命名空间中浏览文件系统, Linux 不允许您超出虚拟化的根目录。下面的绘图显示了文件系统的一部分,其中包含了/drives/xx文件夹中的多个 “虚拟” 文件系统根目录,每个文件夹包含不同的数据。

filesystem namespace example

其它命名空间

除了 PID 和文件系统命名空间之外,还有 其他类型的名称空间 。 Docker 允许您使用它们以实现所需的隔离量。 例如,用户命名空间允许您将容器内的用户映射到外部的不同用户。这可以用于将容器内的根用户映射到外部的非根用户,因此容器内的进程在内部就像管理员一样,在外部它没有特权。

可堆叠图像层和写时复制

现在,我们对硬件和系统资源隔离如何帮助我们构建容器有了更详细的了解,我们将研究 Docker 存储映像的方式。如前所述,Docker 映像就像是容器的蓝图。它带有启动包含它的应用程序所需的所有依赖关系。但是如何存储这些依赖关系?

Docker 将图像持久保存在可堆叠的层中。一层包含对上一层所做的更改。例如,如果您先安装 Python,然后复制 Python 脚本,则映像将具有两个附加层:一层包含 Python 可执行文件,另一层包含脚本。下图显示了全部基于 Ubuntu 的 Zeppelin,Spring 和 PHP 映像。

可堆叠图像层

为了不存储三次 Ubuntu,层是不可变的并且是共享的。 如果发生改变时,Docker 使用写时复制去复制文件。

基于镜像启动 Docker 容器时,Docker 守护进程将为您提供该镜像中包含的所有层,并将其放入该容器的隔离文件系统命名空间中。可堆叠层、写时复制和文件系统命名空间的组合使您能够完全独立于「安装」在 Docker 主机上的内容来运行容器,而不会浪费大量空间。这就是为什么容器比虚拟机更轻量级的原因之一。

虚拟网桥

现在,我们知道了隔离硬件资源 (控制组) 和系统资源 (命名空间) 的方法,以及如何为每个容器提供独立于主机系统 (镜像层) 的预定义依赖集。最后一个构建模块,即「虚拟网桥」,它可以帮助我们隔离容器内的网络堆栈。

网桥是从多个通信网络或网段创建单个聚合网络的计算机网络设备。让我们看看连接两个网段 (LAN 1 和 LAN 2) 的物理网桥的典型设置:

network bridge

通常我们在 Docker 主机上只有有限的网络接口 (例如物理网卡),所有进程都需要共享对它的访问。为了隔离容器的网络,Docker 允许每个容器创建一个虚拟网络接口。然后,将所有虚拟网络接口连接到主机网络适配器,如下图所示:

docker virtual network bridge

本例中的两个容器在其网络命名空间中有自己的 eth0 网络接口。它映射到 Docker 主机上相应的虚拟网络接口 veth0 veth1。虚拟网桥 docker0 将主机网络接口 eth0 连接到所有容器网络接口。

Docker 为您提供了配置网桥的自由,因此,您可以只向外部公开特定端口,或直接将两个容器连接在一起 (例如,数据库容器和需要访问它的应用程序),而不向外部公开任何内容。

连接点

利用前面描述的技术和功能,我们现在可以 “容器化” 我们的应用程序。虽然可以使用 cgroup、命名空间、虚拟网络适配器等手动创建容器,但 Docker 是一个方便且几乎没有开销的工具。它处理所有手动、配置密集型任务,使软件开发人员而不仅仅是 Linux 专家可以访问容器。

实际上有一位 Docker 工程师提供了一篇 “不错的演讲”,他演示了如何手动创建容器,也解释了我们在这一小节中介绍的细节。

Docker 的机遇和挑战

到现在,很多人每天都在使用 Docker。容器增加了什么好处?Docker 提供了以前没有的东西吗?最后,您对应用程序进行容器化所需的一切在 Linux 中已经存在很长时间了,不是吗?

让我们看看在迁移到基于容器的设置时您所拥有的一些机会 (当然不是详尽的列表)。当然,在采用 Docker 时,不仅有机会,也有挑战,可能会给您带来困难。我们还将在本节中列举一些。

Opportunities

Docker 支持 DevOps。DevOps 理念试图将开发和操作活动连接起来,使开发人员能够自行部署其应用程序。您构建它、运行它。通过基于 Docker 的部署,开发人员可以直接将其工件和所需的依赖项一起发布不用担心依赖冲突。它还允许开发人员编写更复杂的测试并更快地执行它们,例如,在另一个容器中创建一个真实的数据库,并在几秒钟内将其链接到笔记本电脑上的应用程序 (请参见 Testcontainers)。

容器提高了部署的可预测性。不再 “运行” 在我的机器上”。不再有失败的应用程序部署,因为一台计算机安装了不同版本的 Java。您只需构建一次映像,就可以在任何地方运行它 (假设安装了 Linux 内核和 Docker)。

采用率高,与许多著名的集群管理器很好地集成。使用 Docker 的一个重要方面是其周围的软件生态系统。如果您计划进行大规模操作,那么您将无法使用一个或另一个集群管理器。如果你决定让其他人来管理你的部署 (如 Google Cloud、Docker Cloud、Heroku、AWS 等等),或者想维护你自己的集群管理器 (如 Kubernetes、Nomad、Mesos),有很多解决方案可供选择。

轻量级容器支持快速故障恢复或自动扩展。想象一下运行一个在线商店。在圣诞节期间,人们将开始攻击您的 web 服务器,而您当前的设置在容量方面可能不够。考虑到您有足够的免费硬件资源,再启动几个承载 web 应用程序的容器只需几秒钟。也可以通过将容器迁移到新机器来恢复发生故障的机器。

挑战

容器给人一种错误的安全感。在保护应用程序安全方面有许多陷阱。认为把它们放在容器里是保护它们的一种方法是错误的。容器本身并不能保护任何东西。如果有人破解了您的容器化 web 应用程序,他可能会被锁定到名称空间中,但根据设置的不同,有几种方法可以避免这种情况。意识到这一点,并尽可能多地投入到安全性上,就像没有 Docker 一样。

Docker 使人们可以轻松地部署半生不熟的解决方案。选择您最喜欢的软件,并将其名称输入谷歌搜索栏,添加 “Docker”。你可能会在 Dockerhub 上找到至少一个甚至几十个已经公开的包含你的软件的图片。所以为什么不直接执行它,给它一个机会呢?什么会出错?很多事情都会出错。当把东西放进容器里时,它看起来会非常闪亮,令人惊叹,人们也不再关注里面的实际软件和配置了。

(fat)容器反模式会导致大型的、难以管理的部署构件。 我看到过 Docker 映像,这些映像要求您在创建容器时为内部不同的应用程序公开 20 多个端口。Docker 的哲学是一个容器应该做一项工作,你应该把它们组合起来,而不是让它们变得更重。如果您最终将所有工具放在一个容器中,您将失去所有优势,内部可能有不同版本的 Java 或 Python,并最终得到 20 GB 无法管理的映像。
调试某些情况可能仍需要深入的 Linux 知识。您可能听到同事说 XXX 不能与 Docker 一起工作。之所以会发生这种情况,有多种原因。如果某些应用程序不能正确区分它们绑定到的网络接口和它们通告的网络接口,则它们在桥接网络命名空间中运行时会出现问题。另一个问题可能与 cgroups 和名称空间有关,其中共享内存方面的默认设置与您最喜欢的 Linux 发行版上的设置不同,导致在容器内运行时出现 OOM 错误。然而,大多数问题实际上并不与 Docker 相关,而是与应用程序设计不当有关,并且它们并不是那么频繁。但它们仍然需要对 Linux 和 Docker 如何工作有一些更深入的了解,这并不是每个 Docker 用户都有的。

常见问题

容器和虚拟机有什么区别?

在不太深入了解虚拟机 (VM) 体系结构的情况下,让我们从概念层面看两者之间的主要区别。容器在操作系统内部运行,使用内核功能来隔离应用程序。另一方面,VM 需要在操作系统内部运行的管理程序。然后,管理程序创建可由另一组操作系统访问的虚拟硬件。下图比较了基于虚拟机的应用程序设置和基于容器的设置。

vm vs container

如您所见,基于容器的设置具有较小的开销,因为它不需要为每个应用程序添加一个额外的操作系统。这是因为容器管理器 (例如 Docker) 直接使用操作系统功能以更轻量级的方式隔离应用程序。

这是否意味着容器优于虚拟机?这要看情况。这两种技术都有各自的用例,有时甚至可以将它们结合起来,在 VM 中运行容器管理器。有很多博客文章在讨论这两种解决方案的利弊,所以我们现在不打算详细讨论。重要的是要了解差异,不要将容器视为某种 “轻量级虚拟机”,因为它们在内部是不同的。

容器包含什么?

看看容器的定义以及我们到目前为止所学到的知识,我们可以有把握地说,可以使用 Docker 来部署隔离的应用程序。通过将控制组和命名空间与可堆叠的图像层和虚拟网络接口以及虚拟网桥相结合,我们拥有了完全隔离应用程序所需的所有工具,还可能将进程锁定在容器中。现实表明,这并不容易。首先,它需要正确配置,其次,您会注意到完全隔离的容器在大多数情况下没有多大意义。

最后,您的应用程序需要以某种方式产生一些副作用(将数据保存到磁盘,通过网络发送数据包,...)。因此,您最终将通过转发网络流量或将主机卷装入您的文件系统命名空间来打破隔离。也不需要使用所有可用的命名空间功能。虽然默认启用网络、PID 和文件系统命名空间功能,但使用用户 ID 命名空间需要您添加额外的配置选项。

所以假设仅仅通过将某些东西放入容器中就可以保证容器的安全是错误的。例如,AWS 使用一个名为 Firecracker 的轻量级虚拟机引擎来安全和多租户执行短期工作负载。

容器是否能使我的生产环境更稳定?

有些人认为容器可以提高稳定性,因为它们可以隔离错误。如果正确配置的命名空间和 Cgroups 将限制一个进程出现恶意的副作用,那么这是正确的,但实际上需要记住一些事情。

如前所述,容器仅在正确配置时才包含,而且大多数时候您希望它们与系统的其他部分交互。因此,可以说容器有助于提高部署的稳定性,但您应该始终记住,它不会保护您的应用程序不受失败的影响。

结论

Docker 是以或多或少可重现和隔离的方式独立部署应用程序的伟大技术。一如既往,没有万能的解决方案,在选择 Docker 作为您选择的工具之前,您应该了解您在安全性、性能、可部署性、可观察性等方面的要求。

幸运的是,Docker 周围已经有一个巨大的工具生态系统。可以根据需要添加服务发现、容器编排、日志转发、加密等用例的解决方案。我想引用我最喜欢的一条推文来结束这篇帖子:

"把已经坏掉的软件放进 Docker 容器并不会减少它的损坏。" - @sadserver

Docker命令

img

帮助命令

docker version #显示docker的版本信息
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help #万能命令

镜像命令

  • docker images 查看所有本地的主机上的镜像
REPOSITORY         TAG            IMAGE ID            CREATED          SIZE

#解释
REPOSITORY   镜像的创库源
TAG 		镜像的标签
IMAGE ID 	镜像的创建时间
CREATED		镜像的大小
SIZE		镜像的大小

#可选项
-a, --all   #列出所有的镜像
-q, --quiet #只显示镜像的id
  • docker search 搜索镜像
[root@hjz ~]# docker search mysql
NAME                            DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   13338               [OK]                
mariadb                         MariaDB Server is a high performing open sou…   5095                [OK]                
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   654                 [OK]                
percona                         Percona Server is a fork of the MySQL relati…   592                 [OK]                
bitnami/mysql                   Bitnami MySQL Docker Image                      78                                      [OK]
[root@hjz ~]# docker search --help

Usage:	docker search [OPTIONS] TERM

Search the Docker Hub for images

Options:
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print search using a Go template
      --limit int       Max number of search results (default 25)
      --no-trunc        Don't truncate output
 #可选项,通过搜藏来过滤
 --filter = STARS =3000 #搜索出来的镜像就是STARS大于3000的
  • docker pull 下载镜像
#下载镜像 docker pull 镜像[:tag]
[root@hjz ~]# docker pull mysql
Using default tag: latest #如果不写tag,默认就是latest
latest: Pulling from library/mysql
5ed150ed0abe: Pull complete #分层下载,docker iamge 的核心 联合文件系统
0fede58e17ac: Pull complete 
994a6ddd6efe: Pull complete 
028bda79779b: Pull complete 
426fbe9e56a2: Pull complete 
1a00e58dd193: Pull complete 
4a4f64494005: Pull complete 
fba8ab3534a7: Pull complete 
2695938edf88: Pull complete 
3754e2587bed: Pull complete 
1b9f154543e7: Pull complete 
Digest: sha256:147572c972192417add6f1cf65ea33edfd44086e461a3381601b53e1662f5d15
Status: Downloaded newer image for mysql:latest #真实地址

#等价于它
docker pull mysql
docker pull docker.io/library/mysql:latest 

#指定版本下载
[root@hjz ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
0056409b8e89: Pull complete 
219bd535343d: Pull complete 
f220ee65eb90: Pull complete 
7bbb395b2290: Pull complete 
645e487e5f0a: Pull complete 
a9fa38d2e1fb: Pull complete 
e1d9f4f7e8b4: Pull complete 
e03fcfe5d90e: Pull complete 
74c4d4272e30: Pull complete 
e3a8ad6eeebe: Pull complete 
919524a8718b: Pull complete 
Digest: sha256:94176d0ad4ed85767fc0d74b8071387109a0390e7c1afd39788269c96d2dad74
Status: Downloaded newer image for mysql:5.7
#联合文件系统--当下载的文件的内容是有相对重复时:可以复用
  • docker rmi删除镜像
[root@hjz ~]# docker rmi -f 262701d58edd #删除指定的容器

docker rmi -f $(docker images -af)

容器命令

说明:我们有了镜像才可以创建容器

docker pull centos

新建容器并启动

docker run [可选参数] image

#参数说明
--name="Name" 容器名字 tomcat01 tomcar02 用来区分容器
-d 			  后台方式运行
-it			  使用交互方式运行,进行容器查看内容
-p			  指定容器的端口 -p 8080:8080
	-p ip:主机端口:容器端口
	-p 机端口:容器端口  (常用)
	容器端口
-p 				随机指定端口

#测试,启动进入容器
[root@hjz ~]# docker run -it centos /bin/bash
[root@1ae8c19ba05a /]# bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@1ae8c19ba05a /]# exit
exit

列出所有的运行的容器

#docker ps 命令
	#列出当前正在运行的容器	
-a	#列出当前正在运行的容器+带出历史运行过的容器
-n=?#显示最近创建的容器
-q	#只显示ID
[root@hjz ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@hjz ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                          PORTS               NAMES
1ae8c19ba05a        centos              "/bin/bash"         5 minutes ago       Exited (0) About a minute ago                       peaceful_mccarthy

退出容器

exit #退出容器
Ctrl + P +Q#容器不停止退出

删除容器

docker rm 容器id			   #删除指定容器
docker rm -f $(docker ps -aq) #删除全部容器
docker ps -a -q|xargs docker rm #删除所有的容器

启动和停止容器的操作

docker start 容器id		#启动容器
docker restart 容器id		#重启容器
docker stop 容器id		#停止容器
docker kill 容器id		#强制停止当前容器

常用其他命令

后台启动容器

#命令 docker run -d 进行名!
[root@hjz ~]# docker run -d centos
#问题docker ps,发现centos停止了
#常见的坑,docker容器使用后台运行,就必须要有一个前台进程,docker发现没有应用就会自#动停止,nginx 容器启动后,发现自己没有服务就立即停止了,就是没有程序了

查看日志

docker logs
#docker logs -tf --tail 10 容器id

#自己编写一段shell脚本
[root@hjz ~]# docker run -d centos /bin/sh -c "while true;do echo hjz;sleep 1;done"
[root@hjz ~]# docker ps
......
#显示日志
-tf  	#显示日志
--tail number #要显示的日志条数

查看容器中的进程信息

[root@hjz ~]# docker top edc3b9c7cc44
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                1621                1606                0                   11:13               ?                   00:00:00            /bin/sh -c while true;do echo hjz;sleep 1;done
root                1715                1621                0                   11:14               ?                   00:00:00            /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1

查看镜像的元数据

docker inspect 容器的id
.....

进入当前正在运行的容器

#我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置

#命令
docker exec -it 容器id bashShell
#测试
[root@hjz ~]# docker exec -it edc3b9c7cc44 /bin/bash
[root@edc3b9c7cc44 /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@edc3b9c7cc44 /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:03 ?        00:00:00 /bin/sh -c while true;do echo hj
root        76     0  0 08:04 pts/0    00:00:00 /bin/bash
root        99     1  0 08:05 ?        00:00:00 /usr/bin/coreutils --coreutils-p
root       100    76  0 08:05 pts/0    00:00:00 ps -ef
#命令
docker attach 容器id
  • docker exec 进入容器开启一个新的终端,可以在里面操作
  • docker进入容器正在执行的终端,不会启动新的进程

从容器内拷贝文件到主机上

docker cp  容器id:容器内路径 目的主机路径

例子:

[root@hjz ~]# docker run -it centos /bin/bash
[root@75474c95f0cb /]# [root@hjz ~]# 
[root@hjz ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
75474c95f0cb        centos              "/bin/bash"         24 seconds ago      Up 23 seconds                           wizardly_hoover
[root@hjz ~]# docker attach 75474c95f0cb
[root@75474c95f0cb /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@75474c95f0cb /]# cd home
[root@75474c95f0cb home]# ls
[root@75474c95f0cb home]# mkdir a.txt
[root@75474c95f0cb home]# ls
a.txt
[root@75474c95f0cb home]# exit     
exit
[root@hjz ~]# docker cp 75474c95f0cb:/home/a.txt /home
[root@hjz ~]# cd /home
[root@hjz home]# ls
a.txt  hjz
#拷贝是一个手动的过程,未来我们使用-v卷的技术,可以实现同步数据

命令分析

容器

操作 命令(全) 命令(简)
容器的创建 docker container run docker run
容器的列出 docker container ls docker ps
容器的列出(up 和exit) docker container ls -a docker ps -a
容器的停止 docker container stop docker stop
容器的删除 docker container rm <name or docker rm

docker 命令列表

命令 作用
attach 绑定到运行中容器的 标准输入, 输出,以及错误流(这样似乎也能进入容器内容,但是一定小心,他们操作的就是控制台,控制台的退出命令会生效,比如redis,nginx…
build 从一个 Dockerfile 文件构建镜像
commit 把容器的改变 提交创建一个新的镜像
cp 容器和本地文件系统间 复制 文件/文件夹
create 创建新容器,但并不启动(注意与docker run 的区分)需要手动启动。start\stopdiff 检查容器里文件系统结构的更改【A:添加文件或目录 D:文件或者目录删除 C:文件或者目录更改】
events 获取服务器的实时事件
exec 在运行时的容器内运行命令
export 导出容器的文件系统为一个tar文件。commit是直接提交成镜像,export是导出成文件方便传输
history 显示镜像的历史
images 列出所有镜像
import 导入tar的内容创建一个镜像,再导入进来的镜像直接启动不了容器。/docker-entrypoint.sh nginx -g 'daemon of;'docker ps --no-trunc 看下之前的完整启动命令再用他
info 显示系统信息
inspect 获取docker对象的底层信息
kill 杀死一个或者多个容器
load 从 tar 文件加载镜像
login 登录Docker registry
logout 退出Docker registry
logs 获取容器日志;容器以前在前台控制台能输出的所有内容,都可以看到
pause 暂停一个或者多个容器
port 列出容器的端口映射
ps 列出所有容器
pull 从registry下载一个image 或者repository
push 给registry推送一个image或者repository
rename 重命名一个容器
restart 重启一个或者多个容器
rm 移除一个或者多个容器
rmi 移除一个或者多个镜像
run 创建并启动容器
save 把一个或者多个镜像保存为tar文件
search 去docker hub寻找镜像
start 启动一个或者多个容器
stats 显示容器资源的实时使用状态
stop 停止一个或者多个容器
tag 给源镜像创建一个新的标签,变成新的镜像
top 显示正在运行容器的进程
unpause pause的反操作
update 更新一个或者多个docker容器配置
version Show the Docker version information
container 管理容器
image 管理镜像
network 管理网络
volume 管理卷

Docker 镜像

镜像是什么?

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

UnionFS(联合文件系统)

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

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

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

在这里插入图片描述

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

为什么 Docker 镜像要采用这种分层结构呢

最大的一个好处就是 - 共享资源

比如:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,

同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

build

docker image build -t hello .
#-t 后面是标签 .代表当前目录下有dockerfile文件
#推荐
docker image build -t dockerHub的用户ID/hello:1.0 .

重新命名docker镜像的tag

docker image tag 镜像的名字|ID 重命名的镜像名字
docker image tag hello dockerHub的ID/hello
#执行
docker container run -it xxxx/hello python3 /hello.py

commit命令

docker commit 提交容器成为一个新的副本

#命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名字:[tag]

docker数据卷

什么是容器数据卷

docker的理念回顾·:

将应用和环境打包成一个镜像!

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失:数据可以持久化

MySQL,容器删了,删库跑路!MySQL数据可以存储在本地

容器之间可以有一个数据共享的技术!Docker容器中产生的数据,同步到本地!

这就是卷技术!目录的挂载,将我们容器内的目录,挂载到linux上面

总结:容器的持久化和同步操作,容器间数据共享

数据卷命令

docker run -it -v 主机的目录地址:容器目录

具名挂载和匿名挂载

#匿名挂载
docker run -d -p 10020:3306  --name nginx01 -v /etc/nginx nginx

#查看所有卷的情况-
docker volume ls

所有的docker容器内的卷,没有指定目录的情况下都是在:/var/lib/docker/volumes/xxx/_data

拓展

#通过-v 容器内路径 ,ro rw 改变读写权限

docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
#ro  只能从外部改变

Dockerfile

  • 用于构建docker镜像的文件
  • 包含了构建镜像所需要的“指令”
  • 有其特定的语法规则

img

Dckerfile 就是用来构建docker镜像文件,命令脚本~

#创建一个Dockerfile文件
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "---end---"
CMD /bin/bash

docker build -f /home/docker-test-volume/dockerfile -t hjz/centos:1.0 .

COPY和ADD

两者都可以把local的一个文件复制到镜像里面,如果目标目录不存在,则自动创建

FROM python:3.9.5-alpine3.13
COPY hello.py /app/hello.py

比如把本地的hello.py复制到/app目录下。 /app目录不存在则自动创建

ADD如果复制的是一个gzip等压缩文件时,ADD会帮助我们自动的去压缩文件

FROM python:3.9.5-alpine3.13
ADD hello.tar.gz /app/
  • 普通文件复制 - COPY
  • 压缩文件 - · ADD

WORKDIR

#设置工作路径,类似于cd 如果工作路径不存在则创建对应的目录

ARG vs ENV

ARGENV是经常容易混淆的两个Dockerfile的语法,都可以用来设置一个变量,但是有不同

ENV

FROM ubuntu:21.04
ENV VERSION=2.0.1
RUN apt-get update && \
 	apt-get install -y wget && \
	wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz&& \
 	tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz&& \
	mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo&& \
	rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz

ARG

FROM ubuntu:21.04
ARG VERSION=2.0.1
RUN apt-get update && \
 	apt-get install -y wget && \
	wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz&& \
 	tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz&& \
	mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo&& \
	rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz

区别

使用ARG只会在创建容器的时候使用相关的变量,ENV在创建容器后可以依然使用 命令查看env

技巧

  • 不需要打开修改相应的dockerfile文件就可以改变值

docker image build -f .\Dcokerfile-arg -t ipinfo-arg-2.0.0 --build-arg VERSION=2.0.0 .

CMD

CMD可以来设置容器启动时默认会执行的命令

  • 容器启动时默认执行的命令
  • 如果docker container run启动时指定了其他命令,则CMD命令会被忽略
  • 如果定义了多个CMD,只有最后一个会被执行。

dcoker system prune -f 删除所有停止的容器

docker container run --rm -it ipinfo ipinfo 8.8.8.8 在启动容器是就会删除

ENTRYPOINT

可以设置容器启动时要执行的命令

  • ENTRYPOINT 所设置的命令一定会被执行 CMD设置的命令,可以在docker container run 时传入其他命令,覆盖掉CMD的命令
  • ENTRYPOINT 和CMD可以联合使用,ENTRYPOINT设置执行的命令,CMD传递参数

ENTRYPOINTCMD可以同时支持shell格式和Exec格式

数据卷容器

#启动3个容器测试,通过我们自己写的镜像启动
docker run -d --name centos01 -v /home/volume01:volume01 centos

#继承
docker run -d --name centos02 --volumes-from centos01 centos

结论:

容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止,但是你持久到

本地则不会删除

步骤

  1. 编写一个dockerfile 文件
  2. docker build 构成一个镜像文件
  3. docker run 运行镜像
  4. docker push 发布镜像 (DockerHub、阿里云镜像厂库)
FROM  			#一切从这里开始
MAINTAINER		#镜像是谁写的 姓名+邮箱
RUN  			#镜像构建的时候需要运行的命令
ADD 			 #步骤 添加内容
WORKDIR 		#镜像的工作目录
VOLUME			#挂载的目录位置
EXPOSE 			#暴露端口
CMD 			#指定这个容器启动时候要运行的命令,只有最后一个会执行,会被替代
ENTRYPOINT		#指定这个容器执行的命令,可以追加
ONBUILD 		#当构建一个被继承的 Dockerfile这个时候就会运行ONBUILD命令
COPY 			#类似ADD命令,将我们的文件拷贝到镜像中
ENV				#构建的时候设置环境变量

LABEL 			#注释
FROM centos
MAINTAINER hjz<haojingzhaoemail@qq.com>

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash

#构建镜像
#命令 docker build -f dockerfile文件路径 -t 镜像名:[tag] . 注意一定要有 . 点

#docker history 容器ID    查看容器如何写的dockerfile

CMD和ENTRYPOINT有什么区别

CMD 				#指定这个容器启动时候要运行的命令,只有最后一个会执行,会被替代
ENTRYPOINT		     #指定这个容器执行的命令,可以追加

测试:

FROM centos 
CMD ["ls","-a"]

如果执行docker run 容器id会显示正常的数据,但是要是执行docker run 容器id -l就会错误。原因cmd执行会替换命令

FROM centos 
ENTRYPOINT ["ls","-a"]

发布自己的镜像

DockerHub

  1. 地址`https://hub.docker.com/注册自己的账号
  2. 确定这个账号可以登录
  3. 在我们服务器上提交自己的镜像
[root@iZuf6b2qg1ny365ykqvfc0Z ~]# docker login --help

Usage:	docker login [OPTIONS] [SERVER]

Log in to a Docker registry

Options:
  -p, --password string   Password
      --password-stdin    Take the password from stdin
  -u, --username string   Username

  1. 登录完后就可以提交镜像了
docker login -u xxxxx
  1. 提交镜像
docker images 
...
demo laster
...
#先为demo增加一个tag标签
docker tag 镜像id hjz/demo:1.0

#镜像变成
...
hjz/demo	1.0
demo		last
...
#再push镜像到github
docker push hjz/demo:1.0

阿里云镜像服务

  1. 找到阿里云
  2. 容器镜像服务
  3. 创建一个命名空间
  4. 创建容器镜像
  5. 浏览阿里云

Docker网络

基础知识:

ip地址的查看

  • Windows ipConfig
  • Linux ip addr
  • Linux ifConfig

eth0 ---对外通信 docker0 --docker网络

测试网络的连通性

  • ping 命令
  • telnet命令 telnet www.baidu.com 80
  • traceroute 命令 traceroute www.baidu.com 路径跟踪
  • curl命令

清空所有的环境

[root@iZuf6b2qg1ny365ykqvfc0Z ~]# 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:16:3e:2a:57:a2 brd ff:ff:ff:ff:ff:ff
    inet 172.30.105.237/20 brd 172.30.111.255 scope global dynamic eth0#阿里云内外地址
       valid_lft 315115621sec preferred_lft 315115621sec
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:fd:64:18:2a brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0#docker0地址
       valid_lft forever preferred_lft forever
19: veth4a07f4b@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 8e:ae:a4:ae:1e:43 brd ff:ff:ff:ff:ff:ff link-netnsid 1
33: vethca4b8a9@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 36:6e:41:ac:74:20 brd ff:ff:ff:ff:ff:ff link-netnsid 2

docker是如何处理容器网络访问的?

#查看容器内部的网络地址 ip addr 
docker exec -it 容器id ip addr
root@localhost ~]# docker exec -it chemex 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
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
#思考,linux能不能ping 通容器内部

#linux 可以ping 通 docker
#ping 172.17.0.3 是可以ping通的

原理

192.168.0.1 路由器--- 同一个网段是可以ping

192.168.0.3 手机 --- 通的

  1. 我们每启动一个docker容器,docker都会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术
  2. 在启动容器测试,发现了又多一对网卡~!
       valid_lft forever preferred_lft forever
19: veth4a07f4b@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 8e:ae:a4:ae:1e:43 brd ff:ff:ff:ff:ff:ff link-netnsid 1
33: vethca4b8a9@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 36:6e:41:ac:74:20 brd ff:ff:ff:ff:ff:ff link-netnsid 2

我们发现这些网卡都是一对一对的,envth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连接诶着协议,一段彼此连接

正因为有这个特性,env-pair充当一个桥梁,连接各种学你的网络设备

OpenStac Docker 容器之间的连接,OVS的连接,都是使用 env-pair技术

  1. 测试容器之间是否可以ping通--可以

思考一个场景,我们编写了一个微服务,database url=ip; 项目不重启 ,数据库ip换掉了,我们希望可以处理这个问题,可以名字来进行访问容器?

docker run -d -P --name tomcat03 --link tomcat02 tomcat

docker exec -it tomcat03 ping tomcat02

#反向ping无法ping通  docker exec -it tomcat02 ping tomcat03

原理探究:

其实这个Tomcat03就是在本地配置了tomcat02的配置?

docker exec -it tomcat03 cat /etc/host
127.0.0.1 localhost
...
172.18.0.3 tomcat02 312857784cd4
...

本质探究:--link就是我们在host配置中增加了一个172.18.0.3 tomcat02 312857784cd4

我们现在玩Docker 已经不建议使用--link了!

自定义网络!不适用docker0!

docekr0问题:他不支持容器名连接访问!

自定义网络

[root@iZuf6b2qg1ny365ykqvfc0Z ~]# docker network --help

Usage:	docker network COMMAND

Manage networks

Options:


Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

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

查看所有的docker网络:

[root@iZuf6b2qg1ny365ykqvfc0Z ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f88882d941af        bridge              bridge              local
0e4c1f32b3f8        host                host                local
1eed6207af60        none                null                local

网络模式

  • bridge:桥接docker(默认)
  • none:不配置网络
  • host:和宿主机共享网络
  • container:容器网络连通!(用的少,局限性很好)

测试:

#我们直接启动的命令 --net bridge而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -p --name tomcat01 --net bridge tomcat

#docker0 的特点 :默认。域名不能访问 --link可以打通连接!

#我们可以自定义一个网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
#子网最多支持255*255个 默认的网关是192.168.0.1 网络名称是mynet
#查看自己写的网络
docker network inspect mynet

#启动容器
docker run -d -P --name tomcat-net-01  --net mynet tomcat
docker run -d -P --name tomcat-net-02  --net mynet tomcat

网络连通

[root@iZuf6b2qg1ny365ykqvfc0Z ~]# docker connect --help

Usage:	docker COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) 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

Management Commands:
  config      Manage Docker configs
  container   Manage containers
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  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
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  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
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  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
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  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
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

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

连通网络

docker network connect mynet tomcat01
#测试打通 tomcat
#连通之后就是将tomcat01放到mynet网络下
#一个容器两个ip地址
#公网ip 私网ip

Docker Compose

安装

curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
#将可执行权限应用于二进制文件:
sudo chmod +x /usr/local/bin/docker-compose
#创建软链:
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
#测试是否安装成功:
docker-compose version

基本语法

version: "3"  # 指定docker-compose语法版本
services:    # 从以下定义服务配置列表
  server_name:   # 可将server_name替换为自定义的名字,如mysql/php都可以
    container_name: container_name  # 指定实例化后的容器名,可将container_name替换为自定义名
    image: xxx:latest # 指定使用的镜像名及标签
    build:  # 如果没有现成的镜像,需要自己构建使用这个选项
      context: /xxx/xxx/Dockerfile  # 指定构建镜像文件的路径
      dockerfile: ....     # 指定Dockerfile文件名,上一条指定,这一条就不要了
    ports:
      - "00:00"  # 容器内的映射端口,本地端口:容器内端口
      - "00:00"  # 可指定多个
    volumes:
      - test1:/xx/xx  # 这里使用managed volume的方法,将容器内的目录映射到物理机,方便管理
      - test2:/xx/xx  # 前者是volumes目录下的名字,后者是容器内目录
      - test3:/xx/xx  # 在文件的最后还要使用volumes指定这几个tests
    volumes_from:  # 指定卷容器
       - volume_container_name  # 卷容器名
    restarts: always  # 设置无论遇到什么错,重启容器
    depends_on:       # 用来解决依赖关系,如这个服务的启动,必须在哪个服务启动之后
      - server_name   # 这个是名字其他服务在这个文件中的server_name
      - server_name1  # 按照先后顺序启动
    links:  # 与depend_on相对应,上面控制容器启动,这个控制容器连接
      - mysql  # 值可以是- 服务名,比较复杂,可以在该服务中使用links中mysql代替这个mysql的ip
    networks: # 加入指定的网络,与之前的添加网卡名类似
      - my_net  # bridge类型的网卡名
      - myapp_net # 如果没有网卡会被创建,建议使用时先创建号,在指定
    environment: # 定义变量,类似dockerfile中的ENV
      - TZ=Asia/Shanghai  # 这里设置容器的时区为亚洲上海,也就解决了容器通过compose编排启动的 时区问题!!!!解决了容器的时区问题!!!
      变量值: 变量名   # 这些变量将会被直接写到镜像中的/etc/profile
    command: [                        #使用 command 可以覆盖容器启动后默认执行的命令
            '--character-set-server=utf8mb4',            #设置数据库表的数据集
            '--collation-server=utf8mb4_unicode_ci',    #设置数据库表的数据集
            '--default-time-zone=+8:00'                    #设置mysql数据库的 时区问题!!!! 而不是设置容器的时区问题!!!!
    ]
  server_name2:  # 开始第二个容器
    server_name:
      stdin_open: true # 类似于docker run -d
      tty: true  # 类似于docker run -t
volumes:   # 以上每个服务中挂载映射的目录都在这里写入一次,也叫作声明volume
  test1:
  test2:
  test3:
networks:  # 如果要指定ip网段,还是创建好在使用即可,声明networks
  my_net:
    driver: bridge  # 指定网卡类型
  myapp_net:
    driver: bridge 

例子

start.sh

#prepare image
docekr image pull redis
docker image build -t flask-demo
#create network
docker network create -d bridge demo-network
#create container
docker container run -d --name redis-server --network demo-network redis
docker container run -d --network demo-network --name flask-demo --env REDIS_SERVENR=redis-server -p 5000:5000 flask-demo

docker-compose

version: "3.8"

services: 
	flask-demo:
		image: flask-demo:latest
		environment: 
		  - REDIS_HOST=redis-server
		networks:
		  - demo-network
		ports:
		  - 8080:5000

	redis-server:
	  image: redis:latest
	  networks:
	  - demo-network
	  
networks:
	demo-network:

练习

nginx

FROM nginx:1.21.0-alpine
ADD index.html /usr/share/nginx/html/index.html
docker run \
-p 9000:80 \
--name instructor \
--restart=always \
-v /home/data/nginx/instructor/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /home/data/nginx/instructor/nginx/conf/conf.d:/etc/nginx/conf.d \
-v /home/data/nginx/instructor/nginx/log:/var/log/nginx \
-v /home/data/nginx/instructor/nginx/html:/usr/share/nginx/html \
-d nginx
docker run -d -it -p 8090:80 -v /home/demo:/usr/share/nginx/html --name demo nginx


docker run -d -it -p 9001:80 -v /home/data/nginx/admin/nginx:/usr/share/nginx/html --name admin nginx

docker run -d -it -p 80:80 -v /home/data/nginx/love/nginx:/usr/share/nginx/html -v /home/data/nginx/love/conf/nginx.conf:/etc/nginx/nginx.conf -v /home/data/nginx/love/cret:/var/cret --name love nginx

docker run -d -it -p 80:80 -v /home/data/nginx/christmas:/usr/share/nginx/html --name christmas nginx

docker run -d -it -p 80:80 -v /home/data/nginx/love/nginx:/usr/share/nginx/html -v /home/data/nginx/love/conf/hjzweb.conf:/etc/nginx/nginx.conf -v /home/data/nginx/love/cret:/var/cret --name love nginx

配置https

    server {
        listen       80;
        server_name  www.hjzweb.club;
        rewrite ^(.*)$ https://$host$1;
        location / {
                index index.html index.htm;
        }}
	# HTTPS server
    server {
        listen       443 ssl;
        server_name  www.hjzweb.club;
        root html;
        index index.html index.htm;
        ssl_certificate      cert/hjzweb.club_bundle.pem;
        ssl_certificate_key  cert/hjzweb.club.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }
   

server {
    listen 80;
    server_name www.hjzweb.club;
    server_tokens off;
 
    return 301 https://example.xyz$request_uri;
}
server {
    listen 443 ssl http2;
    server_name example.xyz;
    server_tokens off;
 
    ssl_certificate /etc/nginx/ssl/example.pem;
    ssl_certificate_key /etc/nginx/ssl/example.key;
 
    location / {
        proxy_pass http://服务器ip地址:80;
    }
}

ipinfo

基本的linux命令

apt-get update
apt-get install wget
wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz
tar zxf ipinfo_2.0.1_linux_amd64.tar.gz
mv ipinfo_2.0.1_linux_amd64.tar.gz /usr/bin/ipinfo
rm -rf ipinfo_2.0.1_linux_amd64.tar.gz

dockerfile

FROM ubuntu:21.04
RUN apt-get update
RUN apt-get install -y wget
RUN wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz
RUN tar zxf ipinfo_2.0.1_linux_amd64.tar.gz
RUN mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo
RUN rm -rf ipinfo_2.0.1_linux_amd64.tar.gz

每一行的Run命令都会生成一层image layer,导致镜像文件臃肿。

改进

FROM ubuntu:21.04
RUN apt-get update && \
 	apt-get install -y wget && \
	wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz&& \
 	tar zxf ipinfo_2.0.1_linux_amd64.tar.gz&& \
	mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo&& \
	rm -rf ipinfo_2.0.1_linux_amd64.tar.gz

mysql

#获取镜像
docker pull mysql:5.7
#创建容器
docker run -d -p 10020:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
#需要配置密码
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
  • /var/lib/mysql mysql数据库的数据

创建8.0的版本:

$ mkdir -p /usr/mysql/conf /usr/mysql/data
$ chmod -R 755 /usr/mysql/

vim /usr/mysql/conf/my.cnf


[client]
#socket = /usr/mysql/mysqld.sock
default-character-set = utf8mb4
[mysqld]
#pid-file        = /var/run/mysqld/mysqld.pid
#socket          = /var/run/mysqld/mysqld.sock
#datadir         = /var/lib/mysql
#socket = /usr/mysql/mysqld.sock
#pid-file = /usr/mysql/mysqld.pid
datadir = /usr/mysql/data
character_set_server = utf8mb4
collation_server = utf8mb4_bin
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Custom config should go here
!includedir /etc/mysql/conf.d/


docker run --restart=unless-stopped -d --name mysql01 -v /usr/mysql/conf/my.cnf:/etc/mysql/my.cnf -v /usr/mysql/data:/var/lib/mysql -p 10020:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0.16


tomcat

FROM centos
MAINTAINER hjz<haojingzhaoemail@qq.com>

COPY readme.txt /usr/local/readme.txt

ADD jdk-8u11-linux-64.tar.gz /usr/local/
ADD apache-tomcat-9.0.22.tar.gz /usr.local/

RUN yum -y install vim

ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV	CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apcahe-tomcat-9.0.22
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080

CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.22/bin/logs/catalina.out

构建镜像:

docker build -f dockerfile -t diytomcat .

启动容器:

redis

分片+高可用+负载均衡

  1. 创建一个网卡
docker network create redis --subnet 172.38.0.0/16
#查看网络 详细配置信息
docker network inspect redis
#脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.11
cluster-announce-port 6379
clister-announce-bus-port 16379
appendonly yes
EOF
done


docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-aline3.11 redis-server /etc/redis/redis.conf; \


docker run  -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

#进入redis容器
docker exec -it redis-1 /bin/sh

#创建redis 集群
redis-cli --cluster create 172.38.0.11:6379  172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

#使用redis集群
redis-cli -c
#查看集群信息
cluster info
cluster nodes

python

FROM ubuntu:21.04
RUN apt-get update && \
	DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y python3.9 python3-pip python3.9-dev
ADD hello.py /
CMD ["python3","/hello.py"]
  • 添加hello.py 文件到根\目录
FROM buildpack-deps:jessie

# 删除旧的 python
RUN apt-get purge -y python.*

# 使用 UTF-8 编码
ENV LANG C.UTF-8

ENV PYTHON_VERSION 3.6.5

# if this is called "PIP_VERSION", pip explodes with "ValueError: invalid truth value '<VERSION>'"
ENV PYTHON_PIP_VERSION 10.0.1

RUN set -ex \
        && curl -fSL "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" -o python.tar.xz \
        && mkdir -p /usr/src/python \
        && tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \
        && rm python.tar.xz \
        \
        && cd /usr/src/python \
        && ./configure --enable-shared --enable-unicode=ucs4 \
        && make -j$(nproc) \
        && make install \
        && ldconfig \
        && pip3 install --no-cache-dir --upgrade --ignore-installed pip==$PYTHON_PIP_VERSION \
        && find /usr/local -depth \
                \( \
                    \( -type d -a -name test -o -name tests \) \
                    -o \
                    \( -type f -a -name '*.pyc' -o -name '*.pyo' \) \
                \) -exec rm -rf '{}' + \
        && rm -rf /usr/src/python ~/.cache

# make some useful symlinks that are expected to exist
RUN cd /usr/local/bin \
        && ln -s easy_install-3.5 easy_install \
        && ln -s idle3 idle \
        && ln -s pydoc3 pydoc \
        && ln -s python3 python \
        && ln -s python3-config python-config

CMD ["python3"]

Golang

docker pull golang

docker run -it golang /bin/bash

go env -w GO111MODULE=on #开启go mod
 
go env -w GOPROXY="https://goproxy.cn"
 
go env -w GOPATH="/go"  #如果本身就是,那就不需要再改了,可以省略

docker commit 2d5 golang-local

docker run -d -it --name yiqing -p 8081:8081 -v /home/data/go:/go golang-local 

chatGPT

docker run -itd --name wechatbot --restart=always \
 -e APIKEY=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 \
 -e AUTO_PASS=false \
 -e SESSION_TIMEOUT=60s \
 -e MODEL=text-davinci-003 \
 -e MAX_TOKENS=512 \
 -e TEMPREATURE=0.9 \
 -e REPLY_PREFIX=我是来自机器人回复: \
 -e SESSION_CLEAR_TOKEN=下一个问题 \
 docker.mirrors.sjtug.sjtu.edu.cn/qingshui869413421/wechatbot:latest 

进入 --tail -f -n 50 /app/run.log

lantern

docker pull kent72/lantern
docker run -d -p 8787:8787 kent72/lantern

lantern.env

HTTP_PROXY=192.168.1.111:8787
HTTPS_PROXY=192.168.1.111:8787
NO_PROXY="localhost,127.0.0.1,*.local,/var/run/docker.sock"
http_proxy=192.168.1.111:8787
https_proxy=192.168.1.111:8787
no_proxy="localhost,127.0.0.1,*.local,/var/run/docker.sock"
docker run -d --env-file /root/lantern.env --name ubuntu ubuntu bash

例子

docker run -itd --env-file /home/lantern/lantern.env --name wechatbot --restart=always \
 -e APIKEY=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 \
 -e AUTO_PASS=false \
 -e SESSION_TIMEOUT=60s \
 -e MODEL=text-davinci-003 \
 -e MAX_TOKENS=512 \
 -e TEMPREATURE=0.9 \
 -e REPLY_PREFIX=我是来自机器人回复: \
 -e SESSION_CLEAR_TOKEN=下一个问题 \
 docker.mirrors.sjtug.sjtu.edu.cn/qingshui869413421/wechatbot:latest 

xxnet

docker run -itd \
           --rm \
           --sysctl net.ipv6.conf.all.disable_ipv6=0 \
           --privileged \
           --name=xxnet \
           -p "8085:8085" \
           -p "8086:8086" \
           -p "8087:8087" \
           -p "1080:1080" \
           -v "$(pwd)/conf/supervisord/supervisord.conf:/etc/supervisord.conf" \
           -v "$(pwd)/conf/xxnet/gae_proxy/manual.ini:/data/xxnet/data/gae_proxy/manual.ini" \
           -v "$(pwd)/conf/xxnet/launcher/config.yaml:/data/xxnet/data/launcher/config.yaml" \
           -v "$(pwd)/conf/xxnet/x_tunnel/client.json:/data/xxnet/data/x_tunnel/client.json" \
           xxnet

例子

docker run -itd \
           --rm \
           --sysctl net.ipv6.conf.all.disable_ipv6=0 \
           --privileged \
           --name=xxnet \
           -p "8085:8085" \
           -p "8086:8086" \
           -p "8087:8087" \
           -p "1080:1080" \
           codezm/xxnet
           

知识

docker container run 背后发生什么

docker container run -d --publish 80:80 --name webhost nginx

  1. 在本地查找是否有nginx这个image镜像,但是没有发现
  2. 去远程的image registry查找nginx镜像(默认的registry是Docker Hub)
  3. 下载最新版本的nginx镜像(nginx:latest默认)
  4. 基于nginx镜像来创建一个新的容器,并准备运行
  5. 在宿主机上打开80端口并把容器的80端口转发到宿主机上
  6. 启动容器,运行指定的命令(这里是一个shell脚本去启动nginx)

聊一聊scratch镜像

编译c语言文件:

gcc --static -o hello hello.c
FROM scratch
ADD hello /
CMD ["/hello"]

查看镜像的分层

docker image history 镜像的名字/ID

技巧

快速停止/删除

docker stop $(docker ps -aq)
docker rm -f $(docker ps -aq)

过滤查看nginx的地址

docker container run -d --rm --name web -p 8080:80 nginx
#查看容器的地址
docker container inspect --format '{{.NetworkSettings.IPAddress}}' web
posted on   Steam残酷  阅读(144)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示