精华内容
下载资源
问答
  • 深入浅出Docker

    千次阅读 2015-03-20 12:44:29
    深入浅出Docker(一):Docker核心技术预览 深入浅出Docker(二):Docker命令行探秘 深入浅出Docker(三):Docker开源之路 深入浅出Docker(四):Docker的集成测试部署之道 深入浅出Docker(五):基于...

    深入浅出Docker(一):Docker核心技术预览

    http://www.infoq.com/cn/articles/docker-core-technology-preview


    深入浅出Docker(二):Docker命令行探秘

    http://www.infoq.com/cn/articles/docker-command-line-quest


    深入浅出Docker(三):Docker开源之路

    http://www.infoq.com/cn/articles/docker-open-source-road


    深入浅出Docker(四):Docker的集成测试部署之道

    http://www.infoq.com/cn/articles/docker-integrated-test-and-deployment


    深入浅出Docker(五):基于Fig搭建开发环境

    http://www.infoq.com/cn/articles/docker-build-development-environment-based-on-fig


    深入浅出Docker(六):像谷歌一样部署你的应用

    http://www.infoq.com/cn/articles/deploy-your-application-like-google

    展开全文
  • 图15.5 Docker支持Linux重要安全技术 自定义设置某些安全技术会非常复杂,因为这需要用户深入理解安全技术的运作原理,同时还要了解Linux内核的工作机制。希望这些技术在未来能够简化配置的过程,但就现阶段而言,...
  • 图11.6 容器无法直接进行通信 下面列docker network ls命令在刚完成安装的Docker主机上的输出内容。输出内容做了截取处理,只展示了每个主机上的默认网络。注意,网络的名称和创建时使用的驱动名称是一致的...
  • (8)在任意一个管理节点上执行docker node ls命令来列Swarm节点。 $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 0g4rl...babl8 * mgr2 Ready Active Reachable 2xlti...l0nyp mgr3 Ready ...
  • 第二部分 Docker技术
  • 因此,需要划分4个容器并在每个容器中运行一个应用,如图7.3所示。 图7.3 划分4个容器 从更高层面上来讲,Hypervisor是硬件虚拟化(Hardware Virtualization)——Hypervisor将硬件物理资源划分为虚拟资源;另外...
  • 这项任务的目标是尽可能拆解其中的功能特性,并用小而专的工具来实现它。这些小工具可以是可替换的,也可以被第三方拿去用于构建其他工具。这一计划遵循了在UNIX中得以实践并验证过的一种软件哲学:小而专的工具...
  • 第6章 Docker镜像 在本章中会深入介绍Docker镜像的相关内容。本章的目标是能帮助读者建立Docker镜像的整体认知,并且了解镜像的相关基础操作。在接下来的章节中,本书会向读者展示如何构建一个包含应用的镜像(应用...
  • 第4章 纵观Docker 本章的初衷是在继续深入研究Docker之前,对Docker进行一个整体介绍。 本章主要包含两部分内容。 运维(Ops)视角。 开发(Dev)视角。 在运维视角中,主要包括下载镜像、运行新的容器、登录新容器...
  • 第3章 Docker安装 有很多种方式和场景可以安装DockerDocker可以安装在Windows、Mac,当然还有Linux之上。除此之外还可以在云上安装,也可以在个人笔记本电脑上安装,诸如此类的例子有很多。除了前面提到的各种...
  • 第2章 走进Docker 关于容器技术的图书和探讨总是不可避免地涉及Docker。但是当有人提到“Docker”时,可能是指如下3种概念之一。 Docker公司。 Docker的容器运行时和编排引擎。 Docker开源项目(Moby)。 如果读者...
  • 可以通过docker network ls命令列每个节点上的全部网络。 $ docker network ls NETWORK ID NAME DRIVER SCOPE ddac4ff813b7 bridge bridge local 389a7e7e8607 docker_gwbridge bridge local a09f7e6b2ac6 host ...
  • 14.2.2 深入分析Stack文件 Stack文件就是Docker Compose文件。唯一的要求就是version:一项需要是“3.0”或者更高的值。具体可以关注Docker文档中关于Compose文件的最新版本信息。 在Docker根据某个Stack文件部署...
  • requirements.txt列了应用所依赖的Python包。 请根据需要自行查看文件内容。 app.py显然是应用的核心文件,而docker-compose.yml文件将应用的所有组件组织起来。 下面使用Docker Compose将应用启动起来。以下所有...
  • 附录C 延伸 希望读者能对Docker充满自信,并且准备好去参加DCA考试!幸运的是,开始下一步的容器之旅非常简单! C.1 练习 搭建基础架构和运行工作负载从未如此简单。因为Mac版Docker和Windows版Docker的存在,在...
  • 领英上面的组叫作Docker Certified Associate (DCA)。 B.1 其他对考试有帮助的资料 在本书编写时,本书是唯一涵盖DCA认证考试全部内容的资料。 同时还有一份教学视频涵盖了大部分考试内容,并且能帮助读者很好地...
  • 第16章 企业版工具 在本章中,主要关注Docker提供的一些企业级工具,包括如何安装、如何配置、如何备份以及存储。 本章内容会比较长,并且大部分都是技术细节的分步介绍。本书尽量保证内容有趣,不过这确实很难。 ...
  • 在开始更加深入的介绍之前,请务必与负责组织目录服务的团队讨论AD/LDAP的集成方案。让他们从集成之初就参与进来,从而使得集成方案的制定和实施尽可能顺利进行。 UCP的用户和组的数据存储在一个本地数据库中,从而...
  • 客户端叫作docker(在Windows上是docker.exe),daemon叫作dockerd(在Windows上是dockerd.exe)。默认安装方式将客户端和服务端安装在同一台主机上,并且配置通过本地安全PIC Socket进行通信。 Linux:/var/run/...
  • 接下来进行深入了解。 13.2 卷与持久化数据——详解 对于微服务设计模式来说,容器是不错的选择。通常与微服务挂钩的词有暂时以及无状态。所以,微服务就是无状态的、临时的工作负载,同时容器即微服务。因此,我们...
  • 这个命令会列Dockerfile中设置的所有配置项。 4.推送镜像到仓库 在创建一个镜像之后,将其保存在一个镜像仓库服务是一个不错的方式。这样存储镜像会比较安全,并且可以被其他人访问使用。Docker Hub就是这样的一...
  • 为了实现这个目标,微软跟Docker公司、社区展开了深入合作。 实现容器所需的核心Windows内核技术被统称为Windows容器(Windows Container)。用户空间是通过Docker来完成与Windows容器之间交互的,这使得Docker在...
  • 深入浅出 Docker

    2019-09-28 05:19:34
    一、什么Docker 从作用的角度: Docker是一个为开发人员和系统管理员开发、迁移和运行应用程序的平台。应用程序通过Docker打包成Docker Image后,可以实现统一的方式来下载、启动、扩展、删除和迁移,这样方便...

    一、什么Docker

    • 从作用的角度:
    Docker是一个为开发人员和系统管理员开发、迁移和运行应用程序的平台。应用程序通过Docker打包成Docker Image后,可以实现统一的方式来下载、启动、扩展、删除和迁移,这样方便了应用程序的部署和运维。
    • 从实现的角度(与虚拟机相比):
    1. 相同:虚拟机与容器都能够虚拟化计算机资源从而提高资源利用率,实现应用隔离与资源独立。

        2. 容器和虚拟机之间的主要区别在于虚拟化层的位置和操作系统资源的使用方式。 

      [对于java开发,要想实现程序的打包和迁徙,我们现有的模式是在一个服务器上安装统一一个jdk,运行多个tomcat,每个tomcat里面一个java应用,大家也知道tomcat不用安装,当我们项目要迁徙的时候也只需要把整个tomcat打包然后在另一台服务器上解压就ok了,也很简单

      每台虚拟机都能够获得唯一的操作系统和负载(应用程序),每个容器化应用都会共享相同的操作系统(单个主机操作系统)

      相比于虚拟机,容器拥有更高的资源使用效率,因为它并不需要为每个应用分配单独的操作系统——实例规模更小、创建和迁移速度也更快。云提供商十分热衷于容器技术,因为在相同的硬件设备当中,可以部署数量更多的容器实例 。

    二、基于docker的wordpress博客搭建   小例子

    • 一、 项目介绍

    1、简介

    docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

    本项目使用Docker搭建了一个WordPress应用,基础架构包含一个Nginx服务器来路由/代理请求、WordPress应用服务器 来部署应用以及MySQL数据库来提供存储。

    本项目的搭建环境使用腾讯云平台的云服务器,系统版本为ubuntu 64位。

    2、架构

    构建一个简单的基础框架,其上运行一个WordPress的自包含实 例,WordPress是被全世界很多公司和作家使用的流行博客工具。这个基础架构包含一个Nginx服务器来路由/代理请求,WordPress应用服 务器来部署应用以及MySQL数据库来提供存储。最终的架构类似于: 

    • 二、 实施过程

    1、安装虚拟机和ubuntu系统

     下载VMware Workstation Pro安装,新建虚拟机并安装ubuntu系统。

     进入terminal并获得root权限。

     

    2安装docker环境

    使用百度的命令进行软件安装。

     

    3查看docker信息

    通过docker info 命令可以查看当前docker的运行信息。

    (提示:Cannot connect to the Docker daemon. Is the docker daemon running on this host?

    可以使用serivce docker start来启动docker服务。)

    4配置docker加速器

    由于docker自带的镜像源在国外,下载镜像的速度不理想。所以可以使用国内的镜像源进行加速,如daocloud的仓库。

     curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://acef54a4.m.daocloud.io 

    5创建数据库容器

    容器名为wordpress-db, 同时设置数据库密码。

    docker run --name wordpress-db -e MYSQL_ROOT_PASSWORD=mysecretpassword -d mysql

     

    参数的含义如下:

    -name表示分配给新容器的名字(或者标签)

    -e设置容器的环境变量,指定MySQL实例的密码,已有配置文档可以在MySQL Docker Hub中找到。

    -d指定Docker在后台运行容器。

     

    6创建wordpress容器

     

    docker run --name wordpress-app --link wordpress-db:mysql -d wordpress

    -link wordpress-db:mysql这个参数告诉Docker创建网络连接到wordpress-db容器(之前创建出来的),使得两个容器间能够网络通信。

    查看容器的状态

    docker ps

     

    进入wordpress中使用ping命令,确认wordpress已经连接上数据库。

    docker exec -i -t wordpress-app bash

    ping mysql

     

    7安装配置nginx容器

    使用nginx作为web访问的代理,配置文件。

    cd /usr/local     //进入该目录

    mkdir wordpress-nginx    //定义名为wordpress-nginx子目录

    cd /usr/local/wordpress-nginx   .//进入该目录

    vi default.conf          //定义名为default.conf文件

     

    #Default.conf 这是nginx的配置文件

    server {

    listen       80;

    server_name  localhost;

    error_log /var/log/nginx/error.log warn;

    location / {

        proxy_pass http://wordpress-app:80/;

        proxy_redirect http://server_name http://wordpress-app:80/;

        proxy_set_header   Host               $host;

        proxy_set_header   X-Forwarded-For    $proxy_add_x_forwarded_for;

        proxy_set_header   X-Forwarded-Proto  http;

    }

    error_page   500 502 503 504  /50x.html;

    location = /50x.html {

        root   /usr/share/nginx/html;

     }

    }

     

    使用Dockerfile来安装nginx

    vi Dockerfile

    # this is Dockerfile Infomation

    FROM nginx

    COPY default.conf /etc/nginx/conf.d/default.conf

     接着

     

    安装nginx并启动

    docker build -t wordpress-nginx .

    docker run -d --name=wordpress-nginx --link=wordpress-app:wordpress-app -p 80:80 wordpress-nginx

    指定了参数-p 80:80,这是告诉Docker暴露容器的80端口,这样可以从Docker的宿主机器外部访问该容器。

    docker ps

    我们指定了参数-p 80:80,这是告诉Docker暴露容器的80端口,这样可以从Docker的宿主机器外部访问该容器。 

     

    8web浏览器访问并安装

    • 三、 项目总结

     通过本次项目实践,对Linux中Docker技术有了初步的认知,实施过程中出现了一系列问题包括虚拟机操作系统安装失败,用vi命令新建文件时命令不会使用,按照阿里云安装文档安装docker加速器时失败等等等,不过通过上网搜索资料,询问同学等方式解决了,特别感谢林辉同学的指导。

    整个环境的搭建用了两天左右的时间,对我们严谨科研态度和团队协作能力的培养有了很大帮助,另外对于虚拟机、linux系统、docker技术实现应用隔离与资源独立的优点等知识点都有了初步认识,对后续的深入学习具有很大的帮助。

     

    参考网址:http://www.open-open.com/lib/view/open1423537959420.html

    转载于:https://www.cnblogs.com/simpleDi/p/6024901.html

    展开全文
  • 深入浅出Docker系列

    千次阅读 2016-08-22 20:11:22
    深入浅出Docker(一):Docker核心技术预览深入浅出Docker(二):Docker命令行探秘深入浅出Docker(三):Docker开源之路深入浅出Docker(四):Docker的集成测试部署之道深入浅出Docker(五):基于Fig搭建开发...
    展开全文
  • Docker 容器简介 参考: [1] 深入浅出Docker.

    Docker 容器简介

    容器是镜像的运行时实例。正如从虚拟机模板上启动 VM 一样,用户也同样可以从单个镜像上启动一个或多个容器。虚拟机和容器最大的区别是容器更快并且更轻量级——与虚拟机运行在完整的操作系统之上相比,容器会共享其所在主机的操作系统/内核。

    下图为使用单个 Docker 镜像启动多个容器的示意图:
    在这里插入图片描述
    启动容器的简便方式是使用 docker container run 命令。该命令可以携带很多参数,在其基础的格式 docker container run 中,指定了启动所需的镜像以及要运行的应用。docker container run -it ubuntu /bin/bash 则会启动某个 Ubuntu Linux 容器,并运行 Bash Shell 作为其应用;如果想启动 PowerShell 并运行一个应用,则可以使用命令 docker container run -it microsoft- /powershell:nanoserver pwsh.exe

    -it 参数可以将当前终端连接到容器的 Shell 终端之上。

    容器随着其中运行应用的退出而终止。在上面两个示例中,Linux 容器会在 Bash Shell 退出后终止,而 Windows 容器会在 PowerShell 进程终止后退出。

    一个简单的验证方法就是启动新的容器,并运行 sleep 命令休眠 10s。容器会启动,然后运行休眠命令,在 10s 后退出。如果你在 Linux 主机(或者在 Linux 容器模式下的 Windows 主机上)运行 docker container run alpine:latest sleep 10 命令,Shell 会连接到容器 Shell 10s 的时间,然后退出;也可以在 Windows 容器上运行 docker container run microsoft/powershell:nanoserver Start-Sleep -s 10 来验证这一点。

    读者可以使用 docker container stop 命令手动停止容器运行,并且使用 docker container start 再次启动该容器。如果再也不需要该容器,则使用 docker container rm 命令来删除容器。

    容器 vs 虚拟机

    容器和虚拟机都依赖于宿主机才能运行。宿主机可以是笔记本,是数据中心的物理服务器,也可以是公有云的某个实例。在下面的示例中,假设宿主机是一台需要运行 4 个业务应用的物理服务器。

    在虚拟机模型中,首先要开启物理机并启动 Hypervisor 引导程序(本课程跳过了 BIOSBootloader 代码等)。一旦 Hypervisor 启动,就会占有机器上的全部物理资源,如 CPURAM、存储和 NICHypervisor 接下来就会将这些物理资源划分为虚拟资源,并且看起来与真实物理资源完全一致。然后 Hypervisor 会将这些资源打包进一个叫作虚拟机(VM)的软件结构当中。这样用户就可以使用这些虚拟机,并在其中安装操作系统和应用。前面提到需要在物理机上运行 4 个应用,所以在 Hypervisor 之上需要创建 4 个虚拟机并安装 4 个操作系统,然后安装 4 个应用。当操作完成后,结构如下图所示:
    在这里插入图片描述
    而容器模型则略有不同。

    服务器启动之后,所选择的操作系统会启动。在 Docker 世界中可以选择 Linux,或者内核支持的容器原语的新版本 Windows。与虚拟机模型相同,OS 也占用了全部硬件资源。在 OS 层之上,需要安装容器引擎(如 Docker)。容器引擎可以获取系统资源,比如进程树、文件系统以及网络栈,接着将资源分割为安全的互相隔离的资源结构,称之为容器。每个容器看起来就像一个真实的操作系统,在其内部可以运行应用。按照前面的假设,需要在物理机上运行 4 个应用。因此,需要划分出 4 个容器并在每个容器中运行一个应用,如下图所示:
    在这里插入图片描述
    从更高层面上来讲,Hypervisor硬件虚拟化(Hardware Virtualization——Hypervisor 将硬件物理资源划分为虚拟资源;另外,容器是操作系统虚拟化(OS Virtualization——容器将系统资源划分为虚拟资源。

    虚拟机的额外开销

    首先我们的目标是在一台物理机上运行 4 个业务相关应用。每种模型示例中都安装了一个操作系统或者 Hypervisor(一种针对虚拟机高度优化后的操作系统)。截至目前,两个模型还很相似,但是也就到此为止了。

    虚拟机模型将底层硬件资源划分到虚拟机当中。每个虚拟机都是包含了虚拟 CPU虚拟 RAM虚拟磁盘等资源的一种软件结构。因此,每个虚拟机都需要有自己的操作系统来声明、初始化并管理这些虚拟资源。但不幸的是,操作系统本身是有其额外开销的。例如,每个操作系统都消耗一点 CPU、一点 RAM、一点存储空间等。每个操作系统都需要独立的许可证,并且都需要打补丁升级,每个操作系统也都面临被攻击的风险。通常将这种现象称作 OS Tax 或者 VM Tax ,每个操作系统都占用一定的资源。

    容器模型具有在宿主机操作系统中运行的单个内核。在一台主机上运行数十个甚至数百个容器都是可能的——容器共享一个操作系统/内核。这意味着只有一个操作系统消耗 CPURAM 和存储资源,只有一个操作系统需要授权,只有一个操作系统需要升级和打补丁。同时,只有一个操作系统面临被攻击的风险。简言之,就是只有一份 OS 损耗!

    在上述单台机器上只需要运行 4 个业务应用的场景中,也许问题尚不明显。但当需要运行成百上千应用的时候,就会引起质的变化。

    另一个值得考虑的事情是启动时间。因为容器并不是完整的操作系统,所以其启动要远比虚拟机快。切记,在容器内部并不需要内核,也就没有定位、解压以及初始化的过程——更不用提在内核启动过程中对硬件的遍历和初始化了。这些在容器启动的过程中统统都不需要!唯一需要的是位于下层操作系统的共享内核是启动了的!最终结果就是,容器可以在 1s 内启动。唯一对容器启动时间有影响的就是容器内应用启动所花费的时间

    这就是容器模型要比虚拟机模型简洁并且高效的原因了。使用容器可以在更少的资源上运行更多的应用,启动更快,并且支付更少的授权和管理费用,同时面对未知攻击的风险也更小。

    检查 Docker daemon

    为了完成下面的示例,需要一个运行 Docker 的主机。对于大多数命令来说,无论是 Linux 还是 Windows 都没有差别。
    通常登录 Docker 主机后的第一件事情是检查 Docker 是否正在运行:

    [root@bogon ~]# docker version
    Client: Docker Engine - Community
     Version:           20.10.1
     API version:       1.41
     Go version:        go1.13.15
     Git commit:        831ebea
     Built:             Tue Dec 15 04:37:17 2020
     OS/Arch:           linux/amd64
     Context:           default
     Experimental:      true
    
    Server: Docker Engine - Community
     Engine:
      Version:          20.10.1
      API version:      1.41 (minimum version 1.12)
      Go version:       go1.13.15
      Git commit:       f001486
      Built:            Tue Dec 15 04:35:42 2020
      OS/Arch:          linux/amd64
      Experimental:     false
     containerd:
      Version:          1.4.3
      GitCommit:        269548fa27e0089a8b8278fc4fc781d7f65a939b
     runc:
      Version:          1.0.0-rc92
      GitCommit:        ff819c7e9184c13b7c2607fe6c30ae19403a7aff
     docker-init:
      Version:          0.19.0
      GitCommit:        de40ad0
    

    当命令输出中包含 ClientServer 的内容时,可以继续下面的示例。如果在 Server 部分中包含了错误码,这表示 Docker daemon 很可能没有运行,或者当前用户没有权限访问。

    如果在 Linux 中遇到无权限访问的问题,需要确认当前用户是否属于本地 Docker UNIX 组。如果不是,可以通过 usermod -aG docker 来添加,然后退出并重新登录 Shell,改动即可生效。

    此外,可以使用如下命令查看 Docker 服务的状态:

    [root@bogon ~]# sudo service docker status
    Redirecting to /bin/systemctl status docker.service
    ● docker.service - Docker Application Container Engine
       Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
       Active: active (running) since 一 2020-12-21 16:02:33 CST; 1h 46min ago
         Docs: https://docs.docker.com
     Main PID: 5617 (dockerd)
        Tasks: 10
       Memory: 163.6M
       CGroup: /system.slice/docker.service
               └─5617 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    
    12月 21 16:02:32 bogon dockerd[5617]: time="2020-12-21T16:02:32.180378658+08:00" level=inf...t."
    12月 21 16:02:32 bogon dockerd[5617]: time="2020-12-21T16:02:32.216274168+08:00" level=inf...ng"
    12月 21 16:02:32 bogon dockerd[5617]: time="2020-12-21T16:02:32.660289412+08:00" level=inf...ng"
    12月 21 16:02:32 bogon dockerd[5617]: time="2020-12-21T16:02:32.876254440+08:00" level=inf...ss"
    12月 21 16:02:32 bogon dockerd[5617]: time="2020-12-21T16:02:32.985981739+08:00" level=inf...ng"
    12月 21 16:02:33 bogon dockerd[5617]: time="2020-12-21T16:02:33.096121883+08:00" level=inf...e."
    12月 21 16:02:33 bogon dockerd[5617]: time="2020-12-21T16:02:33.238774605+08:00" level=inf...0.1
    12月 21 16:02:33 bogon dockerd[5617]: time="2020-12-21T16:02:33.238958499+08:00" level=inf...on"
    12月 21 16:02:33 bogon systemd[1]: Started Docker Application Container Engine.
    12月 21 16:02:33 bogon dockerd[5617]: time="2020-12-21T16:02:33.267356049+08:00" level=inf...ck"
    Hint: Some lines were ellipsized, use -l to show in full.
    

    启动一个简单容器

    启动容器的一个简单的方式是通过 docker container run 命令:

    [user1@localhost ~]$ docker image ls
    REPOSITORY             TAG       IMAGE ID       CREATED        SIZE
    golang                 latest    5f9d35ce5cfe   4 days ago     839MB
    alpine                 <none>    389fef711851   5 days ago     5.58MB
    ubuntu                 18.04     2c047404e52d   3 weeks ago    63.3MB
    nigelpoulton/tu-demo   latest    d5e1e48cf932   8 months ago   104MB
    nigelpoulton/tu-demo   v2        d5e1e48cf932   8 months ago   104MB
    nigelpoulton/tu-demo   v1        6852022de69d   8 months ago   104MB
    

    下面的命令启动了一个简单的容器,其中运行了容器化版本的 Ubuntu Linux

    [user1@localhost ~]$ docker container run -it ubuntu:18.04 /bin/bash
    root@4e121d7a6170:/# 
    

    示例中使用 docker container run 来启动容器,这也是启动新容器的标准命令。命令中使用了 -it 参数使容器具备交互性并与终端进行连接。接下来,命令中指定了具体镜像 ubuntu:18.04 或者 microsoft/powershell:nanoserver 。最终,在命令中指定了运行在容器中的程序,Linux 示例中是 Bash ShellWindows 示例中为 PowerShell

    当敲击 回车键 之后,Docker 客户端选择合适的 API 来调用 Docker daemonDocker daemon 接收到命令并搜索 Docker 本地缓存,观察是否有命令所请求的镜像。在上面引用的示例中,本地缓存已经包含该镜像,否则 Docker 接下来查询在 Docker Hub 中是否存在对应镜像。找到该镜像后,Docker 将镜像拉取到本地,存储在本地缓存当中。

    一旦镜像拉取到本地,daemon 就创建容器并在其中运行指定的应用。

    如果仔细观察,就会发现 Shell 提示符发生了变化,说明目前已经位于容器内部了。在上面的示例中,Shell 提示符已经变为 root@c91bf8660038:/#@ 之后的一长串数字就是容器唯一 ID 的前 12 个字符

    若尝试在容器内执行一些基础命令,可能会发现某些指令无法正常工作。这是因为大部分容器镜像都是经过高度优化的。这意味着某些命令或者包可能没有安装。下面的示例展示了两个命令——一条执行成功,一条执行失败:

    root@4e121d7a6170:/# ls -l
    total 4
    drwxr-xr-x.   2 root root 4096 Nov 19 13:09 bin
    drwxr-xr-x.   2 root root    6 Apr 24  2018 boot
    drwxr-xr-x.   5 root root  360 Dec 22 08:41 dev
    drwxr-xr-x.   1 root root   66 Dec 22 08:41 etc
    drwxr-xr-x.   2 root root    6 Apr 24  2018 home
    drwxr-xr-x.   8 root root   96 May 23  2017 lib
    drwxr-xr-x.   2 root root   34 Nov 19 13:09 lib64
    drwxr-xr-x.   2 root root    6 Nov 19 13:07 media
    drwxr-xr-x.   2 root root    6 Nov 19 13:07 mnt
    drwxr-xr-x.   2 root root    6 Nov 19 13:07 opt
    dr-xr-xr-x. 239 root root    0 Dec 22 08:41 proc
    drwx------.   2 root root   37 Nov 19 13:09 root
    drwxr-xr-x.   1 root root   21 Nov 25 22:25 run
    drwxr-xr-x.   1 root root   21 Nov 25 22:25 sbin
    drwxr-xr-x.   2 root root    6 Nov 19 13:07 srv
    dr-xr-xr-x.  13 root root    0 Dec 22 07:13 sys
    drwxrwxrwt.   2 root root    6 Nov 19 13:09 tmp
    drwxr-xr-x.   1 root root   18 Nov 19 13:07 usr
    drwxr-xr-x.   1 root root   17 Nov 19 13:09 var
    root@4e121d7a6170:/# tree
    bash: tree: command not found
    

    从上面的输出中可以看出,tree 工具包并不是官方 Ubuntu 镜像的一部分。

    容器进程

    上一小节中启动 Ubuntu 容器之时,让容器运行 Bash Shell(/bin/bash)。这使得 Bash Shell 成为容器中运行的且唯一运行的进程。读者可以通过 ps -elf 命令在容器内部查看:

    root@4e121d7a6170:/# ps -elf
    F S UID         PID   PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
    4 S root          1      0  0  80   0 -  4625 wait   08:41 pts/0    00:00:00 /bin/bash
    0 R root         14      1  0  80   0 -  8600 -      09:12 pts/0    00:00:00 ps -elf
    

    上面的输出中看起来好像有两个正在运行的进程,其实并非如此。列表中 PID 为 1 的进程,是容器被告知要运行的 Bash Shell;第二个进程是 ps -elf 命令产生的,这是个临时进程,并且在输出后就已经退出了。也就是说,这个容器当前只运行了一个进程 —— /bin/bash
    这意味着如果通过输入 exit 退出 Bash Shell,那么容器也会退出(终止)。原因是容器如果不运行任何进程则无法存在——杀死 Bash Shell 即杀死了容器唯一运行的进程,导致这个容器也被杀死。这对于 Windows 容器来说也是一样的——杀死容器中的主进程,则容器也会被杀死
    按下 Ctrl-PQ 组合键则会退出容器但并不终止容器运行。这样做会切回到 Docker 主机的 Shell,并保持容器在后台运行。可以使用 docker container ls 命令来观察当前系统正在运行的容器列表:

    root@4e121d7a6170:/# [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
    4e121d7a6170   ubuntu:18.04   "/bin/bash"   35 minutes ago   Up 35 minutes             clever_beaver
    

    当前容器仍然在运行,并且可以通过 docker container exec 命令将终端重新连接到 Docker,理解这一点很重要:

    [user1@localhost ~]$ docker container exec -it 4e121d7a6170 bash
    root@4e121d7a6170:/# 
    

    如上所示,Shell 提示符切换到了容器。如果再次运行 ps 命令,会看到两个 Bash 或者 PowerShell 进程,这是因为 docker container exec 命令创建了新的 Bash 或者 PowerShell 进程并且连接到容器。这意味着在当前 Shell 输入 exit 并不会导致容器终止,因为原 Bash 或者 PowerShell 进程还在运行当中。
    输入 exit 退出容器,并通过命令 docker container ls 来确认容器依然在运行中。果然容器还在运行:

    root@4e121d7a6170:/# exit
    exit
    [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS         PORTS     NAMES
    4e121d7a6170   ubuntu:18.04   "/bin/bash"   8 minutes ago   Up 8 minutes             pedantic_chaplygin
    

    可以使用如下命令停止并删除容器:

    [user1@localhost ~]$ docker container stop 4e121d7a6170
    4e121d7a6170
    [user1@localhost ~]$ docker container rm 4e121d7a6170
    4e121d7a6170
    

    容器生命周期

    容器的生命周期——从创建运行休眠,直至销毁的整个过程。
    执行如下语句创建新的容器:

    [user1@localhost ~]$ docker container run --name percy -it ubuntu:18.04 bash
    root@21deababa995:/# 
    

    这就是新建的容器,名称为“percy”,意指持久化(persistent)。
    接下来把该容器投入使用,将一部分数据写入其中。
    在新容器内部 Shell 中,执行下面的步骤来将部分数据写入到 /tmp 目录下的某个文件中,并确认数据是否写入成功:

    root@21deababa995:/# cd /tmp
    root@21deababa995:/tmp# ls -l
    total 0
    root@21deababa995:/tmp# echo "DevOps FTW" > newfile
    root@21deababa995:/tmp# ls -l
    total 4
    -rw-r--r--. 1 root root 11 Dec 23 06:48 newfile
    root@21deababa995:/tmp# cat newfile
    DevOps FTW
    root@21deababa995:/tmp# 
    

    Ctrl-PQ 组合键退出当前容器。
    现在使用 docker container stop 命令来停止容器运行,切换到 暂停(vacation 状态。可以在 docker container stop 命令中指定容器的名称或者 ID

    root@21deababa995:/tmp# [user1@localhost ~]$ docker container stop percy
    percy
    

    现在运行 docker container ls 命令列出全部处于运行中状态的容器:

    [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    

    新建的容器没有在上面的列表中出现,原因是通过 docker container stop 命令使该容器停止运行。加上 -a 参数,就会显示出全部的容器,包括处于停止状态的:

    [user1@localhost ~]$ docker container ls -a
    CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS                        PORTS     NAMES
    21deababa995   ubuntu:18.04   "bash"        10 minutes ago   Exited (0) 5 minutes ago                percy
    c91bf8660038   ubuntu:18.04   "/bin/bash"   22 hours ago     Exited (255) 26 minutes ago             clever_beaver
    

    现在可以看到该容器显示当前状态为 Exited(0)。停止容器就像停止虚拟机一样。尽管已经停止运行,容器的全部配置和内容仍然保存在 Docker 主机的文件系统之中,并且随时可以重新启动。
    使用 docker container start 命令可以将容器重新启动:

    [user1@localhost ~]$ docker container start percy
    percy
    [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE          COMMAND   CREATED          STATUS          PORTS     NAMES
    21deababa995   ubuntu:18.04   "bash"    12 minutes ago   Up 12 seconds             percy
    

    现在停止的容器已经重新启动了,此时可以确认之前创建的文件是否还存在。使用 docker container exec 命令连接到重启后的容器:

    [user1@localhost ~]$ docker container exec -it percy bash
    root@21deababa995:/# 
    

    Shell 提示符发生变化,提示正在容器内部空间进行操作。
    确认之前创建的文件依然存在,并且文件中仍包含之前写入的数据:

    root@21deababa995:/# cd /tmp
    root@21deababa995:/tmp# ls -l
    total 4
    -rw-r--r--. 1 root root 11 Dec 23 06:48 newfile
    root@21deababa995:/tmp# cat newfile
    DevOps FTW
    root@21deababa995:/tmp# 
    

    从上述操作可以看出,之前创建的文件依然存在,并且文件中包含的数据正是离开的方式!这证明停止容器运行并不会损毁容器或者其中的数据
    尽管上面的示例阐明了容器的持久化特性,还是需要指出卷(volume)才是在容器中存储持久化数据的首选方式
    通过在 docker container rm 命令后面添加 -f 参数来一次性删除运行中的容器是可行的。但是,删除容器的最佳方式还是分两步,先停止容器然后删除。这样可以给容器中运行的应用/进程一个停止运行并清理残留数据的机会:

    root@21deababa995:/tmp# exit
    exit
    [user1@localhost ~]$ docker container stop percy
    percy
    [user1@localhost ~]$ docker container rm percy
    percy
    [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    

    现在容器已经删除了——在系统中消失。如果这是一个有用的容器,那么之后可以作为无服务的工具使用;如果没有用处,则充其量也就是一个蹩脚的终端。
    总结一下容器的生命周期。可以根据需要多次停止、启动、暂停以及重启容器,并且这些操作执行得很快。但是容器及其数据是安全的。直至明确删除容器前,容器都不会丢弃其中的数据。就算容器被删除了,如果将容器数据存储在卷中,数据也会被保存下来。

    优雅地停止容器

    Linux 世界中,大部分容器都会运行单一进程;在 Windows 中可能运行若干个,但是下面的原则对于两者都适用。

    前面的示例中容器正在运行 /bin/bash 应用。当使用 docker container rm -f 来销毁运行中的容器时,不会发出任何告警。这个过程相当暴力——有点像悄悄接近容器后在脑后突施冷枪。毫无征兆地被销毁,会令容器和应用猝不及防,来不及“处理后事”。

    但是,docker container stop 命令就有礼貌多了(就像用枪指着容器的脑袋然后说“你有 10s 时间说出你的遗言”)。该命令给容器内进程发送将要停止的警告信息,给进程机会来有序处理停止前要做的事情。一旦 docker stop 命令返回后,就可以使用 docker container rm 命令删除容器了。

    这背后的原理可以通过 Linux/POSIX 信号来解释。docker container stop 命令向容器内的 PID 1 进程发送了 SIGTERM 这样的信号。就像前文提到的一样,会为进程预留一个清理并优雅停止的机会。如果 10s 内进程没有终止,那么就会收到 SIGKILL 信号。这是致命一击。但是,进程起码有 10s 的时间来“解决”自己。

    docker container rm -f 命令不会先友好地发送 SIGTERM ,这条命令会直接发出 SIGKILL 。就像刚刚所打的比方一样,该命令悄悄接近并对容器发起致命一击。

    利用重启策略进行容器的自我修复

    通常建议在运行容器时配置好重启策略。这是容器的一种自我修复能力,可以在指定事件或者错误后重启来完成自我修复。
    重启策略应用于每个容器,可以作为参数被强制传入 docker container run 命令中,或者在 Compose 文件中声明(在使用 Docker Compose 以及 Docker Stacks 的情况下)。
    截至目前,容器支持的重启策略包括 alwaysunless-stoppedon-failed
    always 策略是一种简单的方式。除非容器被明确停止,比如通过 docker container stop 命令,否则该策略会一直尝试重启处于停止状态的容器。一种简单的证明方式是启动一个新的交互式容器,并在命令后面指定 --restart always 策略,同时在命令中指定运行 Shell 进程。当容器启动的时候,会登录到该 Shell。退出 Shell 时会杀死容器中 PID 为 1 的进程,并且杀死这个容器。但是因为指定了 --restart always 策略,所以容器会自动重启。如果运行 docker container ls 命令,就会看到容器的启动时间小于创建时间。下面请看示例:

    [user1@localhost ~]$ docker container run --name test -it --restart always ubuntu:18.04 /bin/bash
    root@e13028a4992e:/# exit
    exit
    [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
    e13028a4992e   ubuntu:18.04   "/bin/bash"   20 seconds ago   Up 13 seconds             test
    

    注意,容器于 20s 前被创建,但却在 13s 前才启动。这是因为在容器中输入退出命令的时候,容器被杀死,然后 Docker 又重新启动了该容器。
    --restart always 策略有一个很有意思的特性,当 daemon 重启的时候,停止的容器也会被重启。例如,新创建一个容器并指定 --restart always 策略,然后通过 docker container stop 命令停止该容器。现在容器处于 Stopped (Exited) 状态。但是,如果重启 Docker daemon,当 daemon 启动完成时,该容器也会重新启动。

    alwaysunless-stopped 的最大区别,就是那些指定了 --restart unless-stopped 并处于 Stopped (Exited) 状态的容器,不会在 Docker daemon 重启的时候被重启。这个说法可能令人有点迷惑,接下来通过示例进行演示。

    下面创建两个新容器,其中“always”容器指定 --restart always 策略,另一个“unless- stopped”容器指定了 --restart unless-stopped 策略。两个容器均通过 docker container stop 命令停止,接着重启 Docker。结果“always”容器会重启,但是“unless-stopped”容器不会。
    (1)创建两个新容器:

    [user1@localhost ~]$ docker container run -d --name always --restart always ubuntu:18.04 sleep 1d
    [user1@localhost ~]$ docker container run -d --name unless-stopped --restart unless-stopped ubuntu:18.04 sleep 1d
    1e3e911cfb8449e76afb3ac52a87e6725afdd3c72c8c5265203774f75f8e9a14
    [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE          COMMAND       CREATED             STATUS             PORTS     NAMES
    1e3e911cfb84   ubuntu:18.04   "sleep 1d"    53 seconds ago      Up 51 seconds                unless-stopped
    ce0c739d0280   ubuntu:18.04   "sleep 1d"    30 minutes ago      Up 30 minutes                always
    e13028a4992e   ubuntu:18.04   "/bin/bash"   About an hour ago   Up About an hour             test
    

    现在有两个运行的容器了。一个叫作“always”,另一个叫作“unless-stopped”
    (2)停止两个容器:

    [user1@localhost ~]$ docker container stop always unless-stopped
    always
    unless-stopped
    [user1@localhost ~]$ docker container ls -a
    CONTAINER ID   IMAGE          COMMAND       CREATED             STATUS                        PORTS     NAMES
    1e3e911cfb84   ubuntu:18.04   "sleep 1d"    4 minutes ago       Exited (137) 19 seconds ago             unless-stopped
    ce0c739d0280   ubuntu:18.04   "sleep 1d"    34 minutes ago      Exited (137) 19 seconds ago             always
    e13028a4992e   ubuntu:18.04   "/bin/bash"   About an hour ago   Up About an hour                        test
    

    (3)重启 Docker
    重启 Docker 的过程在不同的操作系统上可能不同。在实验环境中执行如下语句:

    [user1@localhost ~]$ sudo service docker restart
    Redirecting to /bin/systemctl restart docker.service
    

    (4)一旦 Docker 重启成功,检查两个容器的状态:

    [user1@localhost ~]$ docker container ls -a
    CONTAINER ID   IMAGE          COMMAND       CREATED             STATUS                       PORTS     NAMES
    1e3e911cfb84   ubuntu:18.04   "sleep 1d"    8 minutes ago       Exited (137) 4 minutes ago             unless-stopped
    ce0c739d0280   ubuntu:18.04   "sleep 1d"    38 minutes ago      Up About a minute                      always
    e13028a4992e   ubuntu:18.04   "/bin/bash"   About an hour ago   Up About a minute                      test
    
    

    注意到“always”容器(启动时指定了 --restart always 策略)已经重启了,但是“unless-stopped”容器(启动时指定了 --restart unless-stopped 策略)并没有重启。
    on-failure 策略会在退出容器并且返回值不是 0 的时候,重启容器。就算容器处于 stopped 状态,在 Docker daemon 重启的时候,容器也会被重启。
    如果读者使用 Docker Compose 或者 Docker Stack,可以在 service 对象中配置重启策略,示例如下:

    version: "3.5"
    services:
      myservice:
        <Snip>
        restart_policy:
          condition: always | unless-stopped | on-failure
    

    Web 服务器示例

    现在来看一个 Linux Web 服务器示例。在该示例中,会使用到我用于 Pluralsight 视频教程网站中的一个镜像。这个镜像会在 8080 端口启动一个相当简单的 Web 服务。
    因为实验环境中默认启动了 TCP 占用了 80 端口,所以需要预先执行如下命令将其清掉

    $ sudo fuser -k 80/tcp
    

    使用 docker container stop 以及 docker container rm 命令清理当前系统中的全部容器,然后运行下面的 docker container run 命令:

    [user1@localhost ~]$ docker container run -d --name webserver -p 80:8080 nigelpoulton/pluralsight-docker-ci
    Unable to find image 'nigelpoulton/pluralsight-docker-ci:latest' locally
    latest: Pulling from nigelpoulton/pluralsight-docker-ci
    729ec3a6ada3: Pull complete 
    f0a3eea3dca0: Pull complete 
    e07851c50ad6: Pull complete 
    f78e7cd1f8dc: Pull complete 
    7cad1fbd2f07: Pull complete 
    22835c51693f: Pull complete 
    Digest: sha256:61bc64850a5f2bfbc65967cc33feaae8a77c8b49379c55aaf05bb02dcee41451
    Status: Downloaded newer image for nigelpoulton/pluralsight-docker-ci:latest
    docker: Error response from daemon: Conflict. The container name "/webserver" is already in use by container "cf2b5aea3107832a2dda83ad9ecab4307b4428193d33705f662760d2c8b85c74". You have to remove (or rename) that container to be able to reuse that name.
    See 'docker run --help'.
    

    注意,当前 Shell 提示符并未发生变化。这是因为使用了 -d 参数启动容器,并在后台运行。这种后台启动的方式不会将当前终端连接到容器当中。

    该示例在 docker container run 命令中抛出了一些额外的参数:
    我们已经知道 docker container run 会启动一个新容器,但是这次使用 -d 参数替换了 -it-d 表示后台模式,告知容器在后台运行。

    然后为容器命名,并且指定了 -p 80:8080-p 参数将 Docker 主机的端口映射到容器内。本例中,将 Docker 主机的 80 端口映射到了容器内的 8080 端口。这意味着当有流量访问主机的 80 端口的时候,流量会直接映射到容器内的 8080 端口。之所以如此是因为当前使用的镜像,其 Web 服务监听了 8080 端口。这意味着容器启动时会运行一个 Web 服务,监听 8080 端口。

    最终,命令中还指定 Docker 所使用的镜像:nigelpoulton/pluralsight-docker-ci 。这个镜像不一定保持更新,并且可能存在缺陷。

    使用 docker container ls 命令可以查看当前运行的容器以及端口的映射情况。端口信息按照 host-port:container-port 的格式显示:

    [user1@localhost ~]$ docker container ls
    CONTAINER ID   IMAGE          COMMAND       CREATED             STATUS          PORTS     NAMES
    ce0c739d0280   ubuntu:18.04   "sleep 1d"    54 minutes ago      Up 17 minutes             always
    e13028a4992e   ubuntu:18.04   "/bin/bash"   About an hour ago   Up 17 minutes             test
    

    docker container stopdocker container pausedocker container startdocker container rm 命令同样适用于容器。同时,持久性的规则也适用于容器——停止或暂停容器并不会导致容器销毁,或者内部存储的数据丢失

    查看容器详情

    在前面的示例当中,可能发现当运行 docker container run 命令的时候,并没有指定容器中的具体应用。但是容器却启动了一个简单的 Web 服务。这是如何发生的?
    当构建 Docker 镜像的时候,可以通过嵌入指令来列出希望容器运行时启动的默认应用。如果运行 docker image inspect 命令来查看运行容器时使用的镜像,就能看到容器启动时将要运行的应用列表了:

    [user1@localhost ~]$ docker image inspect nigelpoulton/pluralsight-docker-ci |grep -A 20 ContainerConfig
            "ContainerConfig": {
                "Hostname": "5e6c8e135f35",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "8080/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
                ],
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "CMD [\"/bin/sh\" \"-c\" \"cd /src && node ./app.js\"]"
    

    Cmd 一项中展示了容器将会执行的命令或应用,除非在启动的时候读者指定另外的应用。如果去掉示例脚本中的转义字符,可以得到这样的命令:/bin/sh -c "cd /src && node ./app.js这是基于该镜像的容器会默认运行的应用
    在构建镜像时指定默认命令是一种很普遍的做法,因为这样可以简化容器的启动。这也为镜像指定了默认的行为,并且从侧面阐述了镜像的用途——可以通过 inspect 镜像的方式来了解所要运行的应用。

    参考:
    [1] 深入浅出Docker.

    展开全文
  • 深入浅 出Docker 一 Docker核心技术预览 1. 背景 1.1. 由PaaS到Container 2013年2月 前Glu ter的CEO Ben Golub和dotCloud的CEO Solomon Hyke 坐在一起聊天时 Solomon谈到想把 dotCloud内部使用的Container容器技术...
  • 深入浅出Docker一Docker核心技术预览 1. 背景 1.1. 由PaaS到Container 2013年2月前Gluster的CEO Ben Golub和dotCloud的CEO Solomon Hykes坐在一起聊天时Solomon谈到想把dotCloud内部使用的Container容器技术单独拿...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,902
精华内容 1,960
关键字:

深入浅出docker