docker_dockerfile - CSDN
docker 订阅
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 [1] 展开全文
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。 [1]
信息
编程语言
Go
类    别
操作系统层虚拟化
提供商
Docker,Inc.
许可协议
Apache License 2.0
中文名
应用容器引擎
发行日期
2013年
外文名
Docker
Docker简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。一个完整的Docker有以下几个部分组成:Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源。Docker自2013年以来非常火热,无论是从 github 上的代码活跃度,还是Redhat在RHEL6.5中集成对Docker的支持, 就连 Google 的 Compute Engine 也支持 docker 在其之上运行。一款开源软件能否在商业上成功,很大程度上依赖三件事 - 成功的 user case(用例), 活跃的社区和一个好故事。 dotCloud 之家的 PaaS 产品建立在docker之上,长期维护且有大量的用户,社区也十分活跃,接下来我们看看docker的故事。 面对上述几个问题,docker设想是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。这样,交付一个软件,就是一系列标准化组件的集合的交付,如同乐高积木,用户只需要选择合适的积木组合,并且在最顶端署上自己的名字(最后一个标准化组件是用户的app)。这也就是基于docker的PaaS产品的原型。Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。Docker 容器通过 Docker 镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。 [3]  Docker采用 C/S架构 Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。 客户端和服务端既可以运行在一个机器上,也可通过 socket 或者RESTful API 来进行通信。Docker daemon 一般在宿主主机后台运行,等待接收来自客户端的消息。 Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟 Docker daemon 交互。 [4]  在docker的网站上提到了docker的典型场景:由于其基于LXC的轻量级虚拟化的特点,docker相比KVM之类最明显的特点就是启动快,资源占用小。因此对于构建隔离的标准化的运行环境,轻量级的PaaS(如dokku), 构建自动化测试和持续集成环境,以及一切可以横向扩展的应用(尤其是需要快速启停来应对峰谷的web应用)。Docker并不是全能的,设计之初也不是KVM之类虚拟化手段的替代品,简单总结几点:针对1-2,有windows base应用的需求的基本可以pass了; 3-5主要是看用户的需求,到底是需要一个container还是一个VM, 同时也决定了docker作为 IaaS 不太可行。针对6,7虽然是docker本身不支持的功能,但是可以通过其他手段解决(disk quota, mount --bind)。总之,选用container还是vm, 就是在隔离性和资源复用性上做权衡。另外即便docker 0.7能够支持非AUFS的文件系统,但是由于其功能还不稳定,商业应用或许会存在问题,而AUFS的稳定版需要kernel 3.8, 所以如果想复制dotcloud的成功案例,可能需要考虑升级kernel或者换用ubuntu的server版本(后者提供deb更新)。这也是为什么开源界更倾向于支持ubuntu的原因(kernel版本) Docker并非适合所有应用场景,Docker只能虚拟基于Linux的服务。Windows Azure 服务能够运行Docker实例,但到目前为止Windows服务还不能被虚拟化。可能最大的障碍在于管理实例之间的交互。由于所有应用组件被拆分到不同的容器中,所有的服务器需要以一致的方式彼此通信。这意味着任何人如果选择复杂的基础设施,那么必须掌握应用编程接口管理以及集群工具,比如Swarm、Mesos或者Kubernets以确保机器按照预期运转并支持故障切换。Docker在本质上是一个附加系统。使用文件系统的不同层构建一个应用是有可能的。每个组件被添加到之前已经创建的组件之上,可以比作为一个文件系统更明智。分层架构带来另一方面的效率提升,当你重建存在变化的Docker镜像时,不需要重建整个Docker镜像,只需要重建变化的部分。可能更为重要的是,Docker旨在用于弹性计算。每个Docker实例的运营生命周期有限,实例数量根据需求增减。在一个管理适度的系统中,这些实例生而平等,不再需要时便各自消亡了。针对Docker环境存在的不足,意味着在开始部署Docker前需要考虑如下几个问题。首先,Docker实例是无状态的。这意味着它们不应该承载任何交易数据,所有数据应该保存在数据库服务器中。其次,开发Docker实例并不像创建一台虚拟机、添加应用然后克隆那样简单。为成功创建并使用Docker基础设施,管理员需要对系统管理的各个方面有一个全面的理解,包括Linux管理、编排及配置工具比如Puppet、Chef以及Salt。这些工具生来就基于命令行以及脚本。 [5]  Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。同VM的方式不同, LXC 其并不是一套硬件虚拟化方法 - 无法归属到全虚拟化、部分虚拟化和半虚拟化中的任意一个,而是一个操作系统级虚拟化方法, 理解起来可能并不像VM那样直观。所以我们从虚拟化到docker要解决的问题出发,看看他是怎么满足用户虚拟化需求的。用户需要考虑虚拟化方法,尤其是硬件虚拟化方法,需要借助其解决的主要是以下4个问题:LXC所实现的隔离性主要是来自kernel的namespace, 其中pid, net, ipc, mnt, uts 等namespace将container的进程, 网络, 消息, 文件系统和hostname 隔离开。pid namespace之前提到用户的进程是lxc-start进程的子进程, 不同用户的进程就是通过pidnamespace隔离开的,且不同 namespace 中可以有相同PID。具有以下特征:正是因为以上的特征,所有的LXC进程在docker中的父进程为docker进程,每个lxc进程具有不同的namespace。同时由于允许嵌套,因此可以很方便的实现 LXC in LXCnet namespace有了 pid namespace, 每个namespace中的pid能够相互隔离,但是网络端口还是共享host的端口。网络隔离是通过netnamespace实现的,每个net namespace有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个container的网络就能隔离开来。LXC在此基础上有5种网络类型,docker默认采用veth的方式将container中的虚拟网卡同host上的一个docker bridge连接在一起。ipc namespacecontainer中进程交互还是采用linux常见的进程间交互方法(interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同VM不同,container 的进程间交互实际上还是host上具有相同pid namespace中的进程间交互,因此需要在IPC资源申请时加入namespace信息 - 每个IPC资源有一个的 32bit ID。mnt namespace类似chroot,将一个进程放到一个特定的目录执行。mnt namespace允许不同namespace的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同chroot不同,每个namespace中的container在/proc/mounts的信息只包含所在namespace的mount point。uts namespaceUTS(“UNIX Time-sharing System”) namespace允许每个container拥有独立的hostname和domain name,   使其在网络上可以被视作一个独立的节点而非Host上的一个进程。user namespace每个container可以有不同的 user 和 group id, 也就是说可以以container内部的用户在container内部执行程序而非Host上的用户。有了以上6种namespace从进程、网络、IPC、文件系统、UTS和用户角度的隔离,一个container就可以对外展现出一个独立计算机的能力,并且不同container从OS层面实现了隔离。   然而不同namespace之间资源还是相互竞争的,仍然需要类似ulimit来管理每个container所能使用的资源 - LXC 采用的是cgroup。 [6]  cgroups 实现了对资源的配额和度量。 cgroups 的使用非常简单,提供类似文件的接口,在 /cgroup目录下新建一个文件夹即可新建一个group,在此文件夹中新建task文件,并将pid写入该文件,即可实现对该进程的资源控制。具体的资源配置选项可以在该文件夹中新建子 subsystem ,{子系统前缀}.{资源项} 是典型的配置方法,如memory.usage_in_bytes 就定义了该group 在subsystem memory中的一个内存限制选项。另外,cgroups中的 subsystem可以随意组合,一个subsystem可以在不同的group中,也可以一个group包含多个subsystem - 也就是说一个 subsystem。关于术语定义A *cgroup* associates a set of tasks with a set of parameters for one   or more subsystems.   A *subsystem* is a module that makes use of the task grouping   facilities provided by cgroups to treat groups of tasks in   particular ways. A subsystem is typically a "resource controller" that   schedules a resource or applies per-cgroup limits, but it may be   anything that wants to act on a group of processes, e.g. a   virtualization subsystem.我们主要关心cgroups可以限制哪些资源,即有哪些subsystem是我们关心。cpu : 在cgroup中,并不能像硬件虚拟化方案一样能够定义CPU能力,但是能够定义CPU轮转的优先级,因此具有较高CPU优先级的进程会更可能得到CPU运算。   通过将参数写入cpu.shares,即可定义改cgroup的CPU优先级 - 这里是一个相对权重,而非绝对值。当然在cpu这个subsystem中还有其他可配置项,手册中有详细说明。cpusets : cpusets 定义了有几个CPU可以被这个group使用,或者哪几个CPU可以供这个group使用。在某些场景下,单CPU绑定可以防止多核间缓存切换,从而提高效率memory : 内存相关的限制blkio : block IO相关的统计和限制,byte/operation统计和限制(IOPS等),读写速度限制等,但是这里主要统计的都是同步IOnet_cls, cpuacct , devices , freezer 等其他可管理项。 [7]  借助于namespace的隔离机制和cgroup限额功能,LXC提供了一套统一的API和工具来建立和管理container, LXC利用了如下 kernel 的features: [8]  LXC 向用户屏蔽了以上 kernel 接口的细节, 提供了如下的组件大大简化了用户的开发和使用工作:LXC 旨在提供一个共享kernel的 OS 级虚拟化方法,在执行时不用重复加载Kernel, 且container的kernel与host共享,因此可以大大加快container的 启动过程,并显著减少内存消耗。在实际测试中,基于LXC的虚拟化方法的IO和CPU性能几乎接近 baremetal 的性能 [9]  , 大多数数据有相比 Xen具有优势。当然对于KVM这种也是通过Kernel进行隔离的方式, 性能优势或许不是那么明显, 主要还是内存消耗和启动时间上的差异。在参考文献 [10]  中提到了利用iozone进行 Disk IO吞吐量测试KVM反而比LXC要快,而且笔者在device mapping driver下重现同样case的实验中也确实能得到如此结论。参考文献从网络虚拟化中虚拟路由的场景(网络IO和CPU角度)比较了KVM和LXC, 得到结论是KVM在性能和隔离性的平衡上比LXC更优秀 - KVM在吞吐量上略差于LXC, 但CPU的隔离可管理项比LXC更明确。关于CPU, DiskIO, network IO 和 memory 在KVM和LXC中的比较还是需要更多的实验才能得出可信服的结论。Docker对container的使用基本是建立在LXC基础之上的,然而LXC存在的问题是难以移动 - 难以通过标准化的模板制作、重建、复制和移动 container。在以VM为基础的虚拟化手段中,有image和snapshot可以用于VM的复制、重建以及移动的功能。想要通过container来实现快速的大规模部署和更新, 这些功能不可或缺。Docker 正是利用AUFS来实现对container的快速更新 - 在docker0.7中引入了storage driver, 支持AUFS, VFS, device mapper, 也为BTRFS以及ZFS引入提供了可能。 但除了AUFS都未经过dotcloud的线上使用,因此我们还是从AUFS的角度介绍。AUFS (AnotherUnionFS) 是一种 Union FS, 简单来说就是支持将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)的文件系统, 更进一步地, AUFS支持为每一个成员目录(AKA branch)设定'readonly', 'readwrite' 和 'whiteout-able' 权限, 同时AUFS里有一个类似分层的概念, 对 readonly 权限的branch可以逻辑上进行修改(增量地, 不影响readonly部分的)。通常 Union FS有两个用途, 一方面可以实现不借助 LVM, RAID 将多个disk和挂在到一个目录下, 另一个更常用的就是将一个readonly的branch和一个writeable的branch联合在一起,Live CD正是基于此可以允许在 OS image 不变的基础上允许用户在其上进行一些写操作。Docker在AUFS上构建的container image也正是如此,接下来我们从启动container中的linux为例介绍docker在AUFS特性的运用。 典型的Linux启动到运行需要两个FS - bootfs + rootfs (从功能角度而非文件系统角度)(图1)bootfs (boot file system) 主要包含 bootloader 和 kernel, bootloader主要是引导加载kernel, 当boot成功后 kernel 被加载到内存中后 bootfs就被umount了.rootfs (root file system) 包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs 如下(图2): 典型的Linux在启动后,首先将 rootfs 置为 readonly, 进行一系列检查, 然后将其切换为 “readwrite” 供用户使用。在docker中,起初也是将 rootfs 以readonly方式加载并检查,然而接下来利用 union mount 的将一个 readwrite 文件系统挂载在 readonly 的rootfs之上,并且允许再次将下层的 file system设定为readonly 并且向上叠加, 这样一组readonly和一个writeable的结构构成一个container的运行目录, 每一个被称作一个Layer。如下(图3):得益于AUFS的特性, 每一个对readonly层文件/目录的修改都 只会存在于上层的writeable层中。这样由于不存在竞争, 多个container可以共享readonly的layer。所以docker将readonly的层称作 “image” - 对于container而言整个rootfs都是read-write的,但事实上所有的修改都写入最上层的writeable层中,image不保存用户状态,可以用于模板、重建和复制。(图4、5) 上层的image依赖下层的image,因此docker中把下层的image称作父image,没有父image的image称作base image (图6)因此想要从一个image启动一个container,docker会先加载其父image直到base image,用户的进程运行在writeable的layer中。所有parent image中的数据信息以及ID、网络和lxc管理的资源限制等具体container的配置,构成一个docker概念上的container。如下(图7):由此可见,采用AUFS作为docker的container的文件系统,能够提供如下好处: 1.节省存储空间 - 多个container可以共享base image存储2.快速部署 - 如果要部署多个container,base image可以避免多次拷贝3.内存更省 - 因为多个container共享base image, 以及OS的disk缓存机制,多个container中的进程命中缓存内容的几率大大增加4.升级更方便 - 相比于 copy-on-write 类型的FS,base-image也是可以挂载为可writeable的,可以通过更新base image而一次性更新其之上的container5.允许在不更改base-image的同时修改其目录中的文件 - 所有写操作 都发生在最上层的writeable层中,这样可以大大增加base image能共享的文件内容。以上5条 1-3 条可以通过 copy-on-write 的FS实现, 4可以利用其他的union mount方式实现, 5只有AUFS实现的很好。这也是为什么Docker一开始就建立在AUFS之上。由于AUFS并不会进入linux主干 (According to Christoph Hellwig, linux rejects all union-type filesystems but UnionMount.),   同时要求kernel版本3.0以上(docker推荐3.8及以上),因此在RedHat工程师的帮助下在docker0.7版本中实现了driver机制, AUFS只是其中的一个driver, 在RHEL中采用的则是Device Mapper的方式实现的container文件系统。grsec是linux kernel安全相关的patch, 用于保护host防止非法入侵。由于其并不是docker的一部分,我们只进行简单的介绍。grsec可以主要从4个方面保护进程不被非法入侵:安全永远是相对的,这些方法只是告诉我们可以从这些角度考虑container类型的安全问题可以关注的方面。
收起全文
精华内容
参与话题
  • Docker最佳实战第一节

    2017-08-18 20:59:52
    让学员在最短的时间内了解如何上手使用Docker,配合精心设计的范例,以及范例代码的演化过程,学员可以可以直观地看到Docker在实际项目中的应用,可能碰到的问题,如何解决,以及如何改进项目的开发过程。
  • 与sgy一起开启你的Docker之路 关键词: Docker; mac; Docker中使用gdb无法进入断点,无法调试; 写在前面 这篇博客适合谁? 对于Docker并不了解,只是有一点模糊的感觉,觉得Docker可以当成虚拟机用之类的 只是...

    与sgy一起开启你的Docker之路

    关键词: Docker; mac; Docker中使用gdb无法进入断点,无法调试;

    更新1: 看起来之前那一版博文中参考资料部分引用的外站链接太多,被系统自动屏蔽了,我说怎么只有我能看别人都看不了我这篇博文。CSDN在外链识别上还要加强啊。我已经改好了,现在各位都能正常浏览本文了,不会404了
    更新2: 不对,不是因为外链的缘故,其他人访问仍然是404,WTF?CSDN药丸?
    更新3: 本文在短短一年时间里已经积累阅读量超过四万余次并收获很多好评也帮到了不少朋友(见评论区)。如果您觉得这篇文写得不错;或者您也像博主一样在找资料的时候被垃圾转载、胡乱复制的博文气的肝颤;请务必用万分之一秒的时间为本文点个赞,既对作者表示认同,又为后面来这儿的朋友提供一下对这篇博文质量的参考。---- sgy@2018/10/17

    写在前面

    • 这篇博客适合谁?
      • 对于Docker并不了解,只是有一点模糊的感觉,觉得Docker可以当成虚拟机用之类的
      • 只是下载了Docker软件,对于怎么配置,怎么玩,第一步干什么,完全一无所知
      • 本文适用于mac,PC用户不保证文章的效果,现在离开来得及
    • 网上Docker相关的教程都泛滥了,为啥还要写,为啥我要看你的文章
      • 首先欢迎你,能搜索到我的博客就是缘分
      • 其次,确实,现在Docker相关的文章真的太多了,那我为什么还要写呢?原因有三:
        • 其一,文章是很多,各种1小时入门什么的,相信你已经在知乎看过很多了,我也看过,
          因为我就是从知乎那几篇教程为起点,自己抠出来的,现在把自己的心得和经验贴出来,我觉得既是对自己负责也能服务他人。
        • 其二,我从对Docker只有及其模糊(真的是模糊,我除了知道Docker是跟虚拟系统有关其他啥都不知道),到现在起码一问一不知(对应一问三不知)的状态,大概花了8个小时。这期间全靠我从网络上搜索到的资料。现在用我的话写出来,我觉得对于跟我相同开始情况的小白用户,能省不少时间,所以我要写。
        • 其三,因为我自己是纯靠搜索到的教程和技术文章学习的Docker,我自然是懂得干涩的语言对学习的拖慢。所以我自己写的时候,自然会考虑到这个问题。本文尽量不用技术用语,尽量使用通俗易懂的文字,为进一步拉低Docker的入门门槛作出我自己的贡献。
    • 这篇文章主要是哪方面的Docker文章,纯入门?你做了哪些工作?
      • 很高兴你问了我这个问题。本文主要:
        • 首先对于Docker的概念作出我的解释,尽量通俗易懂
        • 接着针对我用Docker的目的,从最开始的软件下载,到最后push一个自己的镜像到hub,整个过程以白话的形式描述出来,降低入门门槛,节省你的学习时间
      • 我做了哪些工作?这是个好问题!
        • 首先,我一直都很好奇Docker这个东西,但从来没有机会去使用它。但是,这学期OS课的lab,纯Linux系统编程,虽然使用双系统或者虚拟机都是纯小学生的难易程度了,也不麻烦,但我想,为什么不用Docker呢?用双系统或者虚拟机也太过小儿科!所以,我就这样接触了Docker
        • 那么我使用Docker实现了什么?在lab中,我们需要用到的是纯终端下的gcc工具链还有vim等,那么这就是我需要的全部软件了!于是我在Docker中实现了「gcc+gdb
          +vim」环境,并push到了hub中。
    • 你这篇博客有没有抄别人的?
      • 额,我学习Docker时确实看了很多很多(真的是很多)文章,现在写这篇博客,除了自己的经验心得,自然还得去看那些文章。但我能保证的是,我写的都是取精华去糟粕,不然这篇文章就不必存在了你说是不是?
      • 参考资料会在文后统一附上,谢谢!

    好了,闲话说完,我们开始吧!

    入门Docker,你要下载什么?注册什么?

    • Docker.app你肯定是要下载的!

    Docker for mac,这个你肯定要下载:点我下载Docker for mac的社区免费版本

    • 注册Docker官方账号,你需要它!

    注册一个Docker的官方账号,有利而无害,相信我!点我注册Docker Cloud官方账号

    Docker安装好,账号也注册后,点击桌面顶栏的Docker图标,点击sign in,登陆你的Docker账号。

    • 注册DaoCloud账号,获取加速服务!

    不可否认,有时直接从Docker官方往本地pull镜像会十分缓慢。。。这时我们可以通过国内的Docker服务提供商免费获取加速pull镜像服务,阿里网易好像都有这种服务,我选择的是DaoCloud:点我注册DaoCloud账号

    注册后登陆DaoCloud,找到这个按钮:

    docker1.png

    接着,按照它的步骤,为自己添加Docker加速服务

    docker2

    • 到此准备工作结束,进入下一部分!

    要想入门Docker,首先你需要理解Docker!

    我也不扯淡了,直接上我对Docker的理解:(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)

    Docker,可以说是一个终端命令行的虚拟机,但更准确的说法,其实应该是一个虚拟环境。比如,你想要在PC上无缝使用Linux么?那么虚拟机并不是你唯一的出路,你还有Docker!我更愿意称Docker为一个容器,当然这只是Docker的一个狭义解释,Docker不止是一个容器。Docker包含3个重要概念:

    • 一个,是镜像(Image),镜像是静态的、可以被用户互相分享的文件。我们玩过双系统和虚拟机的人都知道,首先你需要一个.iso镜像,才能安装系统。Docker中的镜像也是这个东西,镜像是静态的,你不能对他操作,只能pull别人的镜像或者push自己的镜像。
    • 还有一个,是容器(Container),前面说过,镜像是静态不可操作的,只能被分享和下载,那什么是能被操作的呢?就是容器里!容器可以理解为镜像的动态状态,也就是我们虚拟机中系统装好后的状态,其实这么说是不对的,容器最符合的描述应该是Linux的iso文件的Live CD模式,比如我们玩双系统时都进入过Live CD模式,不安装系统而直接进入系统,很神奇是吧,Docker的容器就是这个概念,只不过更加轻量更加迅速便捷。但是Live CD的害处就是你关机后作出的修改安装的软件全部gg,容器也是一样,一旦被直接推出,之前安装的gcc啊vim啊啥的就会全部gg掉。如果要保存修改,就需要将当前容器封装成一个新的镜像,这样下次启动这个新的镜像后之前作出的修改还都在。
    • 最后,是仓库(Repository)。各位在前面看到我写的pull和push什么的,有没有晕?不知道各位对于git熟悉不熟悉,Docker中的仓库很像git的代码仓库,你可以pull自己之前push到自己仓库的镜像到本地,也可以pull别人push到公共仓库的镜像到自己本地。说白了就是百度云盘,你可以上传(push)自己做好环境的Docker上去,也可以下载(pull)自己云端的镜像到本地。同时,我们知道百度云最大的特点就是分享(你懂的嘿嘿嘿),类比Docker,如果你得到百度云分享链接(别人的镜像名字、标签和别人的用户名),你还可以下载(pull)别人分享的镜像到自己的本地,别人也可以下载(pull)你的镜像,因为Docker仓库都是公共的。当然,每个免费用户有一个名额把自己的一个镜像设为私有,也就是禁止被分享给别人,类比百度云上你自己保存的而没有被生成分享链接的小姐姐。

    接下来来张高大上的概念图,各位看个热闹2333

    docker3.png

    接下来就是实战了!打开你的iTerm2!(我是iTerm2党2333,打开普通terminal也行,这个不影响)

    • 查看Docker版本信息

    终端输入:
    docker version
    

    显示的我的版本信息

     ~$ docker version
    Client:
     Version:      17.06.2-ce
     API version:  1.30
     Go version:   go1.8.3
     Git commit:   cec0b72
     Built:        Tue Sep  5 20:12:06 2017
     OS/Arch:      darwin/amd64
     ...
     //omitted by sgy(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)
     ...
    

    不过我一般不需要那么多信息,所以一直用的是docker -v命令

    • 是时候pull你的第一个镜像下来的!

    Docker安装好后是不会自带镜像的,你需要从仓库自己pull一个镜像下来,自己制作自己的镜像也是一个道理,你可以通过在已有的镜像基础上生成自己的镜像或者看一下这篇博客: 随便百度的如何创建自己Docker镜像得到的教程

    Docker镜像官方好像只提供Linux,这个很容易想,windows和mac是要交钱的吧大概?

    搜索ubuntu的Docker镜像docker search ubuntu,这个如果你想要什么centos,直接改就行,不区分写法,我的返回结果:

    ~$ docker search ubuntu
    NAME                               DESCRIPTION                                     STARS   OFFICIAL   AUTOMATED
    ubuntu                             Ubuntu is a Debian-based Linux operating s...   6636                [OK]
    dorowu/ubuntu-desktop-lxde-vnc     Ubuntu with openssh-server and NoVNC            131                 [OK]
    rastasheep/ubuntu-sshd             Dockerized SSH service, built on top of of...   105                 [OK]
    ansible/ubuntu14.04-ansible        Ubuntu 14.04 LTS with ansible                   86                  [OK]
    ubuntu-upstart                     Upstart is an event-based replacement for ...   80                  [OK]
    neurodebian                        NeuroDebian provides neuroscience research...   40                  [OK]
    ubuntu-debootstrap                 debootstrap --variant=minbase --components...   31                  [OK]
    ...
    //omitted by sgy(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)
    ...
    

    拉取官方最新版的ubuntu镜像:docker pull ubuntu:latest,其中的latest是一个标签(tag),表示是当前最新版本。你应该得到的信息,类似这样的

    ~$ docker pull ubuntu:latest
    Trying to pull repository docker.io/library/ubuntu ... 
    latest: Pulling from docker.io/library/ubuntu
    aed158d74952: Pull complete 
    773ae8273d14: Pull complete 
    d1d487w88782: Pull complete 
    cd3d6cd6c0cf: Pull complete 
    8d73bu79120c: Pull complete 
    Digest: sha256:35bc48a1ca97c3f74rhf378hj92hd82j29i4hf4hf84nf0dhnsid232de8d8
    Status: Downloaded newer image for docker.io/ubuntu:latest
    

    你输入的命令实际上相当于docker pull registry.hub.docker.com/ubuntu:latest命令,即从注册服务器registry.hub.docker.com中的名为ubuntu的仓库中下载标签为latest的镜像。

    由于我的lab统一要求,ubuntu需要14.04版本,所以我在hub里面搜了搜,找到了一个用户分享的14.04 64位纯净镜像(base image),下面将他的镜像扒下来

    ~$ docker pull chug/ubuntu14.04x64
    

    这个用户还有很多其他版本的ubuntu系统,12 13 14的32位64位都有,全是纯净镜像。

    • 查看你本地的镜像仓库!

    把初始镜像拉下来后,就可以启动它了,不过,可以先使用docker images命令查看你自己的本地镜像,我随便找了个例子,你的也应该是类似这样的:

    ~$ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    docker.io/ubuntu    16.04               e4415b714b62        11 days ago         128.1 MB
    docker.io/ubuntu    latest              e4415b714b62        11 days ago         128.1 MB
    docker.io/ubuntu    12.04               aefa163f7a7e        11 days ago         103.5 MB
    docker.io/centos    latest              0584b3d2cf6d        3 weeks ago         196.5 MB
    

    从网上一个教程中找到以下说法,比我说的好,那就看这个吧!

    在列出信息中,可以看到几个字段信息:

    • 来自于哪个仓库,比如 ubuntu
    • 镜像的标记,比如 16.04
    • 它的 ID 号(唯一),比如e4415b714b62
    • 创建时间
    • 镜像大小

    其中镜像的 ID 唯一标识了镜像,注意到 ubuntu:16.04 和 ubuntu:latest具有相同的镜像 ID ,说明它们实际上是同一镜像。 TAG 信息用来标记来自同一个仓库的不同镜像。例如 ubuntu 仓库中有多个镜像,通过 TAG 信息来区分发行版本,例如10.04 、 12.04 、 12.10 、 13.04 、 14.04 等。例如可以使用docker run -t -i ubuntu:16.04 /bin/bash命令指定使用镜像ubuntu:16.04来启动一个容器。如果不指定具体的标记,则默认使用latest标记信息。

    • 启动你的镜像并尽情安装软件吧!

    以下内容均以我自己pull下来的chug的初始镜像为例:

    现在你已经有一个初始的镜像了,注意这个里面是什么都没有的,连vim都没装,是精简到不能再精简的镜像了。

    首先启动它:

    ~$ docker run -it chug/ubuntu14.04x64 /bin/bash
    root@aa97ba3292ce:/#
    

    -it 表示运行在交互模式,是-i -t的缩写,即-it是两个参数:-i和-t。前者表示打开并保持stdout,后者表示分配一个终端(pseudo-tty)一般这个模式就是可以启动bash,然后和容器有命令行的交互

    可以看到我们终端的字头变成root@aa97ba3292ce:/#了,这就意味着我们的镜像已经创建了一个容器实例。现在我们可以对这个“ubuntu系统”进行操作了

    比如安装vim:

    root@aa97ba3292ce:/# apt-get install vim
    Reading package lists... Done
    Building dependency tree... Done
    The following extra packages will be installed:
      file libexpat1 libffi6 libgpm2 libmagic1 libpython2.7 libpython2.7-minimal libpython2.7-stdlib libsqlite3-0 libssl1.0.0 mime-support vim-common vim-runtime
    Suggested packages:
      gpm ctags vim-doc vim-scripts
    The following NEW packages will be installed:
      file libexpat1 libffi6 libgpm2 libmagic1 libpython2.7 libpython2.7-minimal libpython2.7-stdlib libsqlite3-0 libssl1.0.0 mime-support vim vim-common vim-runtime
    0 upgraded, 14 newly installed, 0 to remove and 0 not upgraded.
    Need to get 10.7 MB of archives.
    After this operation, 50.7 MB of additional disk space will be used.
    Do you want to continue? [Y/n]
    

    看到我没有用sudo,是因为本来就已经是超级用户(root)状态了。

    同理按照我自己的需求,我安装了gcc和gdb

    • 想退出容器?很简单!

    如果使用exit,命令退出,则容器的状态处于Exit,而不是后台运行。如果想让容器一直运行,而不是停止,可以使用快捷键 ctrl+p ctrl+q 退出,此时容器的状态为Up。

    查看当前正在运行的容器:

    ~$ docker ps
    CONTAINER ID     IMAGE        COMMAND      CREATED       STATUS       PORTS        NAMES
    aa97ba3292ce  chug/ubuntu14.04x64   "/bin/bash"    7 minutes ago  Up 7 minutes   relaxed_hoover
    

    看到当前有一个ID为aa97ba3292ce的容器(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)

    启动、停止、重启容器aa97ba3292ce的命令:

    ~$ docker start aa97ba3292ce
    ~$ docker stop aa97ba3292ce
    ~$ docker restart aa97ba3292ce
    

    后台启动一个容器后,如果想进入到这个容器,可以使用attach命令:

    ~$ docker attach aa97ba3292ce
    
    • 软件装完,想保存环境?commit帮你!

    将容器转化为一个镜像,即执行commit操作,完成后可使用docker images查看

    root@aa97ba3292ce:/#exit //先退出容器
    ~$ docker commit -m "ubuntu with vim" -a "sgy" aa97ba3292ce sgy/ubuntu:vim
    ~$ docker images
    REPOSITORY                    TAG    IMAGE ID         CREATED             SIZE
    sgy/ubuntu                    vim    52166e4475ed     5 seconds ago       358.1 MB
    chug/ubuntu14.04x64           latest 0584b3d2cf6d     9 days ago          196.5 MB
    

    其中,-m指定说明信息;-a指定用户信息;aa97ba3292ce代表容器的id;sgy/ubuntu:vim指定目标镜像的用户名、仓库名和 tag 信息。我这里都是为了博客瞎编的用户名,我自己的用户名也不是sgy,你运行命令的时候使用自己注册Docker时的用户名。

    此时Docker中就有了我们新建的镜像sgy/ubuntu:vim,此镜像和原有的ubuntu镜像区别在于多了个vim工具。此时我们利用新镜像创建的容器,本身就自带vim了。

    启动新创建的镜像,可以看到vim已经自带了。

    ~$ docker run -it sgy/ubuntu:vim /bin/bash
    root@520afc596c51:/# vim --version
    VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Apr  4 2017 18:14:54)
    ...
    //omitted by sgy(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)
    ...
    

    利用exit退出容器。此时Docker引擎中就有了两个容器,可使用docker ps -a查看。

    • 想要删除容器或者镜像?用这个!

    如果想删除容器或者镜像,可以使用rm命令,注意:删除镜像前必须先删除以此镜像为基础的容器(哪怕是已经停止的容器),否则无法删除该镜像,会报错Failed to remove image (e4415b714b62): Error response from daemon: conflict: unable to delete e4415b714b62 (cannot be forced) - image has dependent child images类似这种。

    ~$ docker rm container_id
    ~$ docker rmi image_id
    

    有的时候尽管删除了全部容器,镜像还是无法删除,这时点击mac顶栏中的docker logo,选择restart,然后再试一次rmi,应该就没问题了。(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)

    • 附上一张高大上的Docker命令图

    docker4.png

    • 一次配置,到处使用?那就push到hub上吧!

    因为之前已经在Docker.app中登陆了Docker账号,所以现在直接

    ~$ docker push sgy/ubuntu:vim
    

    就可以了!

    下次到了机房,在ubuntu系统中安装Docker,配置好加速器,启动Docker,docker login登陆自己的账号,然后直接~$ docker pull sgy/ubuntu:vim就可以把你push到hub的已经配置好的环境的镜像给扒下来。做完实验,再push上去就ok了!

    Docker中安装gcc、gdb时遇到的问题

    • add-apt-repository: command not found

    14.04系统解决办法:

    apt-get install software-properties-common
    

    older版本的系统:

    apt-get install python-software-properties
    
    • Docker中使用gdb无法进入断点,无法调试

    加上--privileged参数

    ~$ docker run -it --privileged sgy/ubuntu:vim /bin/bash
    

    结语

    到此本文就结束了,我说得很清楚,这只是一篇入门教程,可以让你从“一问三不知”到达“一问一不知”的状态,再高层次?那就靠自己了!

    hope my blog will be of assistance, peace out : )

    References

    防止系统自动屏蔽,以下链接都被我做了处理,去掉’#'就能正常访问了

    [1] h#ttps://zhuanlan.zhihu.com/p/23599229
    [2] h#ttps://zhuanlan.zhihu.com/p/22259092
    [3] h#ttp://cpper.info/2016/12/03/docker-image-introduction.html
    [4] h#ttp://blog.csdn.net/ture_dream/article/details/52651746
    [5] h#ttp://www.leesven.com/2254.html
    [6] h#ttps://askubuntu.com/questions/778318/how-do-i-install-gcc-6-latest-6-1-on-ubuntu-14-04-lts-make-c14-the-default
    [7] h#ttp://blog.qiniu.com/archives/805
    [8] h#ttp://blog.csdn.net/ziren235/article/details/78064936?locationNum=5&fps=1
    [9] h#ttps://segmentfault.com/a/1190000002766882

    [10] h#ttp://blog.csdn.net/jiang_xinxing/article/details/58025417
    [11] h#ttp://blog.csdn.net/yyw794/article/details/78048372
    [12] h#ttp://p.primeton.com/articles/549ad953e13823790300009d

    (Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)


    visitor tracker
    map_v2.png?cl=0e1633&w=a&t=n&d=5Dq0hF6G3WoDZtrpxkeOQ404RoBOWSzDpckKPBFRCnk&co=0b4975&ct=cdd4d9


    展开全文
  • 这可能是最为详细的Docker入门吐血总结

    万次阅读 多人点赞 2018-12-13 19:33:12
    Docker是什么? 在计算机技术日新月异的今天, Docker 在国内发展的如火如荼,特别是在一线互联网公司, Docker 的使用是十分普遍的,甚至成为了一些企业面试的加分项,不信的话看看下面这张图。 这是我在某...

    Docker是什么?

    在计算机技术日新月异的今天, Docker 在国内发展的如火如荼,特别是在一线互联网公司, Docker 的使用是十分普遍的,甚至成为了一些企业面试的加分项,不信的话看看下面这张图。

    这是我在某招聘网站上看到的招聘 Java开发工程师 的招聘要求,其中有一条熟悉 docker 成为了你快速入职的加分项,由此可见熟悉 docker 在互联网公司的地位之重要。

    当然对于我们 CTF选手 而言,熟悉 docker 可以快速搭建 CTF环境 ,完美地还原比赛真实漏洞的场景,帮助我们快速提升自己。

    市面上已经有很多优秀的教程,但是很多原理性的东西,笔者认为那些教程对初学者而言还是很难理解,感觉没有说清楚(笔者自己都觉得挺懵逼的),为了让初学者少走弯路,我将以我的学习经历以及作为一个 CTF选手 的角度,编写此套教程,来带大家去了解并熟练运用 docker ,祝愿各位读者朋友们学完此套教程后,在未来企业面试中能够多一项加分的筹码,能够帮助到大家,我觉得就很值了。

    既然说了这么多, docker 到底是个什么东西呢?

    我们在理解 docker 之前,首先我们得先区分清楚两个概念,容器虚拟机

    可能很多读者朋友都用过虚拟机,而对容器这个概念比较的陌生。

    我们用的传统虚拟机如 VMware , VisualBox 之类的需要模拟整台机器包括硬件,每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。

    而容器技术是和我们的宿主机共享硬件资源及操作系统,可以实现资源的动态分配。容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。

    容器技术是实现操作系统虚拟化的一种途径,可以让您在资源受到隔离的进程中运行应用程序及其依赖关系。通过使用容器,我们可以轻松打包应用程序的代码、配置和依赖关系,将其变成容易使用的构建块,从而实现环境一致性、运营效率、开发人员生产力和版本控制等诸多目标。容器可以帮助保证应用程序快速、可靠、一致地部署,其间不受部署环境的影响。容器还赋予我们对资源更多的精细化控制能力,让我们的基础设施效率更高。通过下面这幅图我们可以很直观的反映出这两者的区别所在。

    Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。

    而 Linux 容器是 Linux 发展出了另一种虚拟化技术,简单来讲, Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离,相当于是在正常进程的外面套了一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。

    Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker ,就不用担心环境问题。

    总体来说, Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。

    Docker的优势

    Docker相比于传统虚拟化方式具有更多的优势:

    • docker 启动快速属于秒级别。虚拟机通常需要几分钟去启动
    • docker 需要的资源更少, docker 在操作系统级别进行虚拟化, docker 容器和内核交互,几乎没有性能损耗,性能优于通过 Hypervisor 层与内核层的虚拟化
    • docker 更轻量, docker 的架构可以共用一个内核与共享应用程序库,所占内存极小。同样的硬件环境, Docker 运行的镜像数远多于虚拟机数量,对系统的利用率非常高
    • 与虚拟机相比, docker 隔离性更弱, docker 属于进程之间的隔离,虚拟机可实现系统级别隔离
    • 安全性: docker 的安全性也更弱。 Docker 的租户 root 和宿主机 root 等同,一旦容器内的用户从普通用户权限提升为root权限,它就直接具备了宿主机的root权限,进而可进行无限制的操作。虚拟机租户 root 权限和宿主机的 root 虚拟机权限是分离的,并且虚拟机利用如 Intel 的 VT-d 和 VT-x 的 ring-1 硬件隔离技术,这种隔离技术可以防止虚拟机突破和彼此交互,而容器至今还没有任何形式的硬件隔离,这使得容器容易受到攻击
    • 可管理性: docker 的集中化管理工具还不算成熟。各种虚拟化技术都有成熟的管理工具,例如 VMware vCenter 提供完备的虚拟机管理能力
    • 高可用和可恢复性: docker 对业务的高可用支持是通过快速重新部署实现的。虚拟化具备负载均衡,高可用,容错,迁移和数据保护等经过生产实践检验的成熟保障机制, VMware 可承诺虚拟机 99.999% 高可用,保证业务连续性
    • 快速创建、删除:虚拟化创建是分钟级别的, Docker 容器创建是秒级别的, Docker 的快速迭代性,决定了无论是开发、测试、部署都可以节约大量时间
    • 交付、部署:虚拟机可以通过镜像实现环境交付的一致性,但镜像分发无法体系化。 Docker 在 Dockerfile 中记录了容器构建过程,可在集群中实现快速分发和快速部署

    我们可以从下面这张表格很清楚地看到容器相比于传统虚拟机的特性的优势所在:

    特性 容器 虚拟机
    启动 秒级 分钟级
    硬盘使用 一般为MB 一般为GB
    性能 接近原生 弱于
    系统支持量 单机支持上千个容器 一般是几十个

    Docker的三个基本概念

    从上图我们可以看到,Docker 中包括三个基本的概念:

    • Image(镜像)
    • Container(容器)
    • Repository(仓库)

    镜像是 Docker 运行容器的前提,仓库是存放镜像的场所,可见镜像更是 Docker 的核心。

    Image (镜像)

    那么镜像到底是什么呢?

    Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

    镜像(Image)就是一堆只读层(read-only layer)的统一视角,也许这个定义有些难以理解,下面的这张图能够帮助读者理解镜像的定义。

    从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker 内部的实现细节,并且能够在主机的文件系统上访问到。统一文件系统 (union file system) 技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。我们可以在图片的右边看到这个视角的形式。

    Container (容器)

    容器 (container) 的定义和镜像 (image) 几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

    由于容器的定义并没有提及是否要运行容器,所以实际上,容器 = 镜像 + 读写层。

    Repository (仓库)

    Docker 仓库是集中存放镜像文件的场所。镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry (仓库注册服务器)就是这样的服务。有时候会把仓库 (Repository) 和仓库注册服务器 (Registry) 混为一谈,并不严格区分。Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。实际上,一个 Docker Registry 中可以包含多个仓库 (Repository) ,每个仓库可以包含多个标签 (Tag),每个标签对应着一个镜像。所以说,镜像仓库是 Docker 用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。

    通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本 。我们可以通过<仓库名>:<标签>的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签.。

    仓库又可以分为两种形式:

    • public(公有仓库)
    • private(私有仓库)

    Docker Registry 公有仓库是开放给用户使用、允许用户管理镜像的 Registry 服务。一般这类公开服务允许用户免费上传、下载公开的镜像,并可能提供收费服务供用户管理私有镜像。

    除了使用公开服务外,用户还可以在本地搭建私有 Docker Registry 。Docker 官方提供了 Docker Registry 镜像,可以直接使用做为私有 Registry 服务。当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。

    我们主要把 Docker 的一些常见概念如 Image , Container , Repository 做了详细的阐述,也从传统虚拟化方式的角度阐述了 docker 的优势,我们从下图可以直观地看到 Docker 的架构:

    framework

    Docker 使用 C/S 结构,即客户端/服务器体系结构。 Docker 客户端与 Docker 服务器进行交互,Docker服务端负责构建、运行和分发 Docker 镜像。 Docker 客户端和服务端可以运行在一台机器上,也可以通过 RESTful 、 stock 或网络接口与远程 Docker 服务端进行通信。

    docker-framework

    这张图展示了 Docker 客户端、服务端和 Docker 仓库(即 Docker Hub 和 Docker Cloud ),默认情况下Docker 会在 Docker 中央仓库寻找镜像文件,这种利用仓库管理镜像的设计理念类似于 Git ,当然这个仓库是可以通过修改配置来指定的,甚至我们可以创建我们自己的私有仓库。

    Docker的安装和使用

    Docker 的安装和使用有一些前提条件,主要体现在体系架构和内核的支持上。对于体系架构,除了 Docker 一开始就支持的 X86-64 ,其他体系架构的支持则一直在不断地完善和推进中。

    Docker 分为 CE 和 EE 两大版本。 CE 即社区版(免费,支持周期 7 个月), EE 即企业版,强调安全,付费使用,支持周期 24 个月。

    我们在安装前可以参看官方文档获取最新的 Docker 支持情况,官方文档在这里:

    https://docs.docker.com/install/

    Docker 对于内核支持的功能,即内核的配置选项也有一定的要求(比如必须开启 Cgroup 和 Namespace 相关选项,以及其他的网络和存储驱动等), Docker 源码中提供了一个检测脚本来检测和指导内核的配置,脚本链接在这里:

    https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh

    在满足前提条件后,安装就变得非常的简单了。

    Docker CE 的安装请参考官方文档:

    • MacOS:https://docs.docker.com/docker-for-mac/install/
    • Windows:https://docs.docker.com/docker-for-windows/install/
    • Ubuntu:https://docs.docker.com/install/linux/docker-ce/ubuntu/
    • Debian:https://docs.docker.com/install/linux/docker-ce/debian/
    • CentOS:https://docs.docker.com/install/linux/docker-ce/centos/
    • Fedora:https://docs.docker.com/install/linux/docker-ce/fedora/
    • 其他 Linux 发行版:https://docs.docker.com/install/linux/docker-ce/binaries/

    这里我们以 CentOS7 作为本文的演示。

    环境准备

    • 阿里云服务器(1核2G,1M带宽)
    • CentOS 7.4 64位

    由于 Docker-CE 支持 64 位版本的 CentOS7 ,并且要求内核版本不低于 3.10

    首先我们需要卸载掉旧版本的 Docker

    $ sudo yum remove docker \
                      docker-client \
                      docker-client-latest \
                      docker-common \
                      docker-latest \
                      docker-latest-logrotate \
                      docker-logrotate \
                      docker-selinux \
                      docker-engine-selinux \
                      docker-engine

    我们执行以下安装命令去安装依赖包:

    $ sudo yum install -y yum-utils \
               device-mapper-persistent-data \
               lvm2

    这里我事先已经安装过了,所以提示我已经安装了最新版本

    安装Docker

    Docker 软件包已经包括在默认的 CentOS-Extras 软件源里。因此想要安装 docker,只需要运行下面的 yum 命令

    $ sudo yum install docker

    当然在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装:

    curl -fsSL get.docker.com -o get-docker.sh
    sh get-docker.sh

    具体可以参看 docker-install 的脚本:

    https://github.com/docker/docker-install

    执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker CE 的 Edge 版本安装在系统中。

    安装完成后,运行下面的命令,验证是否安装成功:

    docker version
    or
    docker info

    返回docker的版本相关信息,证明 docker 安装成功

    启动Docker-CE

    $ sudo systemctl enable docker
    $ sudo systemctl start docker

    Docker的简单运用---Hello World

    由于服务器日常崩溃了, docker 出了点问题,所以以下案例的演示是基于 Kali Linux 环境下进行的。

    我们通过最简单的 image 文件 hello world,感受一下 Docker 的魅力吧!

    我们直接运行下面的命令,将名为 hello-world 的 image 文件从仓库抓取到本地。

    docker pull library/hello-world

    docker pull images 是抓取 image 文件, library/hello-world 是 image 文件在仓库里面的位置,其中 library 是 image 文件所在的组, hello-world 是 image 文件的名字。

    抓取成功以后,就可以在本机看到这个 image 文件了。

    docker images

    我们可以看到如下结果:

    现在,我们可以运行 hello-world 这个 image 文件

    docker run hello-world

    我们可以看到如下结果:

    输出这段提示以后,hello world 就会停止运行,容器自动终止。有些容器不会自动终止,因为提供的是服务,比如Mysql镜像等。

    是不是很 easy 呢?我们从上面可以看出, docker 的功能是十分强大的,除此之外,我们还可以拉去一些 Ubuntu , Apache等镜像,在未来的教程中我们将会一一提到。

    Docker 提供了一套简单实用的命令来创建和更新镜像,我们可以通过网络直接下载一个已经创建好了的应用镜像,并通过 Docker RUN 命令就可以直接使用。当镜像通过 RUN 命令运行成功后,这个运行的镜像就是一个 Docker 容器啦,容器可以理解为一个轻量级的沙箱, Docker 利用容器来运行和隔离应用,容器是可以被启动、停止、删除的,这并不会影响 Docker 镜像。

    我们可以看看下面这幅图:

    Docker 客户端是 Docker 用户与 Docker 交互的主要方式。当您使用 docker 命令行运行命令时, Docker 客户端将这些命令发送给服务器端,服务端将执行这些命令。 docker 命令使用 docker API 。 Docker 客户端可以与多个服务端进行通信。

    我们将剖析一下 Docker 容器是如何工作的,学习好Docker容器工作的原理,我们就可以自己去管理我们的容器了。

    Docker架构

    在上面的学习中,我们简单地讲解了Docker的基本架构。了解到了Docker 使用的是 C/S 结构,即客户端/服务器体系结构。明白了 Docker 客户端与 Docker 服务器进行交互时, Docker 服务端负责构建、运行和分发 Docker 镜像。 也知道了Docker 客户端和服务端可以运行在一台机器上,可以通过 RESTful 、 stock 或网络接口与远程 Docker 服务端进行通信。

    我们从下图可以很直观的了解到Docker的架构:

    Docker 的核心组件包括:

    1. Docker Client
    2. Docker daemon
    3. Docker Image
    4. Docker Registry
    5. Docker Container

    Docker 采用的是 Client/Server 架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。客户端和服务器可以运行在同一个 Host 上,客户端也可以通过 socket 或 REST API 与远程的服务器通信。可能很多朋友暂时不太理解一些东西,比如 REST API 是什么东西等,不过没关系,在后面的文章中会一一给大家讲解清楚。

    Docker Client

    Docker Client ,也称 Docker 客户端。它其实就是 Docker 提供命令行界面 (CLI) 工具,是许多 Docker 用户与 Docker 进行交互的主要方式。客户端可以构建,运行和停止应用程序,还可以远程与Docker_Host进行交互。最常用的 Docker客户端就是 docker 命令,我们可以通过 docker 命令很方便地在 host 上构建和运行 docker 容器。

    Docker daemon

    Docker daemon 是服务器组件,以 Linux 后台服务的方式运行,是 Docker 最核心的后台进程,我们也把它称为守护进程。它负责响应来自 Docker Client 的请求,然后将这些请求翻译成系统调用完成容器管理操作。该进程会在后台启动一个 API Server ,负责接收由 Docker Client 发送的请求,接收到的请求将通过Docker daemon 内部的一个路由分发调度,由具体的函数来执行请求。

    我们大致可以将其分为以下三部分:

    • Docker Server
    • Engine
    • Job

    Docker Daemon的架构如下所示:

    Docker Daemon 可以认为是通过 Docker Server 模块接受 Docker Client 的请求,并在 Engine 中处理请求,然后根据请求类型,创建出指定的 Job 并运行。 Docker Daemon 运行在 Docker host 上,负责创建、运行、监控容器,构建、存储镜像。

    运行过程的作用有以下几种可能:

    • 向 Docker Registry 获取镜像
    • 通过 graphdriver 执行容器镜像的本地化操作
    • 通过 networkdriver 执行容器网络环境的配置
    • 通过 execdriver 执行容器内部运行的执行工作

    由于 Docker Daemon 和 Docker Client 的启动都是通过可执行文件 docker 来完成的,因此两者的启动流程非常相似。 Docker 可执行文件运行时,运行代码通过不同的命令行 flag 参数,区分两者,并最终运行两者各自相应的部分。

    启动 Docker Daemon 时,一般可以使用以下命令来完成

    docker --daemon = true
    docker –d
    docker –d = true

    再由 docker 的 main() 函数来解析以上命令的相应 flag 参数,并最终完成 Docker Daemon 的启动。

    下图可以很直观地看到 Docker Daemon 的启动流程:

    默认配置下, Docker daemon 只能响应来自本地 Host 的客户端请求。如果要允许远程客户端请求,需要在配置文件中打开 TCP监听。我们可以照着如下步骤进行配置:

    1、编辑配置文件 /etc/systemd/system/multi-user.target.wants/docker.service ,在环境变量 ExecStart 后面添加 -H tcp://0.0.0.0,允许来自任意 IP 的客户端连接。

    2、重启 Docker daemon

    systemctl daemon-reload
    systemctl restart docker.service

    3、我们通过以下命令即可实现与远程服务器通信

    docker -H 服务器IP地址 info

    -H 是用来指定服务器主机, info 子命令用于查看 Docker 服务器的信息

    Docker Image

    Docker 镜像可以看作是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。我们可将 Docker镜像看成只读模板,通过它可以创建 Docker 容器。

    镜像有多种生成方法:

    1. 从无到有开始创建镜像
    2. 下载并使用别人创建好的现成的镜像
    3. 在现有镜像上创建新的镜像

    我们可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称作 Dockerfile ,通过执行 docker build <docker-file> 命令可以构建出 Docker 镜像,在后续的教程中,我们会用一篇专门讨论这个问题。

    Docker Registry

    Docker registry 是存储 docker image 的仓库,它在 docker 生态环境中的位置如下图所示:

    运行docker pushdocker pulldocker search时,实际上是通过 docker daemon 与 docker registry 通信。

    Docker Container

    Docker 容器就是 Docker 镜像的运行实例,是真正运行项目程序、消耗系统资源、提供服务的地方。 Docker Container 提供了系统硬件环境,我们可以使用 Docker Images 这些制作好的系统盘,再加上我们所编写好的项目代码, run 一下就可以提供服务啦。

    Docker组件是如何协作运行容器

    看到这里,我相信各位读者朋友们应该已经对Docker基础架构已经熟悉的差不多了,我们还记得运行的第一个容器吗?现在我们再通过hello-world这个例子来体会一下 Docker 各个组件是如何协作的。

    容器启动过程如下:

    • Docker 客户端执行 docker run 命令
    • Docker daemon 发现本地没有 hello-world 镜像
    • daemon 从 Docker Hub 下载镜像
    • 下载完成,镜像 hello-world 被保存到本地
    • Docker daemon 启动容器

    具体过程可以看如下这幅演示图:

    我们可以通过docker images 可以查看到 hello-world 已经下载到本地

    我们可以通过docker ps 或者 docker container ls 显示正在运行的容器,我们可以看到, hello-world 在输出提示信息以后就会停止运行,容器自动终止,所以我们在查看的时候没有发现有容器在运行。

    我们把 Docker 容器的工作流程剖析的十分清楚了,我们大体可以知道 Docker 组件协作运行容器可以分为以下几个过程:

    1. Docker 客户端执行 docker run 命令
    2. Docker daemon 发现本地没有我们需要的镜像
    3. daemon 从 Docker Hub 下载镜像
    4. 下载完成后,镜像被保存到本地
    5. Docker daemon 启动容器

    了解了这些过程以后,我们再来理解这些命令就不会觉得很突兀了,下面我来给大家讲讲 Docker 常用的一些命令操作吧。

    Docker常用命令

    我们可以通过 docker -h 去查看命令的详细的帮助文档。在这里我只会讲一些平常日常比赛或者生活中我们可能会用的比较多的一些命令。

    例如,我们需要拉取一个 docker 镜像,我们可以用如下命令:

    docker pull image_name

    image_name 为镜像的名称,而如果我们想从 Docker Hub 上去下载某个镜像,我们可以使用以下命令:

    docker pull centos:latest

    centos:lastest 是镜像的名称, Docker daemon 发现本地没有我们需要的镜像,会自动去 Docker Hub 上去下载镜像,下载完成后,该镜像被默认保存到 /var/lib/docker 目录下。

    接着我们如果想查看下主机下存在多少镜像,我们可以用如下命令:

    docker images

    我们要想知道当前有哪些容器在运行,我们可以用如下命令:

    docker ps -a

    -a 是查看当前所有的容器,包括未运行的

    我们该如何去对一个容器进行启动,重启和停止呢?我们可以用如下命令:

    docker start container_name/container_id
    docker restart container_name/container_id
    docker stop container_name/container_id

    这个时候我们如果想进入到这个容器中,我们可以使用 attach 命令:

    docker attach container_name/container_id

    那如果我们想运行这个容器中的镜像的话,并且调用镜像里面的 bash ,我们可以使用如下命令:

    docker run -t -i container_name/container_id /bin/bash

    那如果这个时候,我们想删除指定镜像的话,由于 image 被某个 container 引用(拿来运行),如果不将这个引用的 container 销毁(删除),那 image 肯定是不能被删除。我们首先得先去停止这个容器:

    docker ps
    docker stop container_name/container_id

    然后我们用如下命令去删除这个容器:

    docker rm container_name/container_id

    然后这个时候我们再去删除这个镜像:

    docker rmi image_name

    此时,常用的 Docker 相关的命令就讲到这里为止了,我们在后续的文章中还会反复地提到这些命令。

    Dockerfile是什么

    前面我们已经提到了 Docker 的一些基本概念。以 CTF 选手的角度来看,我们可以去使用 Dockerfile 定义镜像,依赖镜像来运行容器,可以去模拟出一个真实的漏洞场景。因此毫无疑问的说, Dockerfile 是镜像和容器的关键,并且 Dockerfile 还可以很轻易的去定义镜像内容,说了这么多,那么 Dockerfile 到底是个什么东西呢?

    Dockerfile 是自动构建 docker 镜像的配置文件, 用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile 中的命令非常类似于 linux 下的 shell 命令。

    我们可以通过下面这幅图来直观地感受下 Docker 镜像、容器和 Dockerfile 三者之间的关系。

    我们从上图中可以看到, Dockerfile 可以自定义镜像,通过 Docker 命令去运行镜像,从而达到启动容器的目的。

    Dockerfile 是由一行行命令语句组成,并且支持已 # 开头的注释行。

    一般来说,我们可以将 Dockerfile 分为四个部分:

    • 基础镜像(父镜像)信息指令 FROM
    • 维护者信息指令 MAINTAINER
    • 镜像操作指令 RUN 、 EVN 、 ADD 和 WORKDIR 等
    • 容器启动指令 CMD 、 ENTRYPOINT 和 USER 等

    下面是一段简单的Dockerfile的例子:

    FROM python:2.7
    MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>
    COPY . /app
    WORKDIR /app
    RUN pip install -r requirements.txt
    EXPOSE 5000
    ENTRYPOINT ["python"]
    CMD ["app.py"]

    我们可以分析一下上面这个过程:

    • 1、从 Docker Hub 上 pull 下 python 2.7 的基础镜像
    • 2、显示维护者的信息
    • 3、copy 当前目录到容器中的 /app 目录下 复制本地主机的 <src> ( Dockerfile 所在目录的相对路径)到容器里 <dest>
    • 4、指定工作路径为 /app
    • 5、安装依赖包
    • 6、暴露 5000 端口
    • 7、启动 app

    这个例子是启动一个 python flask app 的 Dockerfile ( flask 是 python 的一个轻量的 web 框架),相信大家从这个例子中能够稍微理解了Dockfile的组成以及指令的编写过程。

    Dockerfile常用的指令

    根据上面的例子,我们已经差不多知道了Dockerfile的组成以及指令的编写过程,我们再来理解一下这些常用命令就会得心应手了。

    由于 Dockerfile 中所有的命令都是以下格式:INSTRUCTION argument ,指令 (INSTRUCTION) 不分大小写,但是推荐大写,和sql语句是不是很相似呢?下面我们正式来讲解一下这些指令集吧。

    FROM

    FROM 是用于指定基础的 images ,一般格式为 FROM <image> or FORM <image>:<tag> ,所有的 Dockerfile 都用该以 FROM 开头,FROM 命令指明 Dockerfile 所创建的镜像文件以什么镜像为基础,FROM 以后的所有指令都会在 FROM 的基础上进行创建镜像。可以在同一个 Dockerfile 中多次使用 FROM 命令用于创建多个镜像。比如我们要指定 python 2.7 的基础镜像,我们可以像如下写法一样:

    FROM python:2.7

    MAINTAINER

    MAINTAINER 是用于指定镜像创建者和联系方式,一般格式为 MAINTAINER <name> 。这里我设置成我的 ID 和邮箱:

    MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>

    COPY

    COPY 是用于复制本地主机的 <src> (为 Dockerfile 所在目录的相对路径)到容器中的 <dest>

    当使用本地目录为源目录时,推荐使用 COPY 。一般格式为 COPY <src><dest> 。例如我们要拷贝当前目录到容器中的 /app 目录下,我们可以这样操作:

    COPY . /app

    WORKDIR

    WORKDIR 用于配合 RUNCMDENTRYPOINT 命令设置当前工作路径。可以设置多次,如果是相对路径,则相对前一个 WORKDIR 命令。默认路径为/。一般格式为 WORKDIR /path/to/work/dir 。例如我们设置/app 路径,我们可以进行如下操作:

    WORKDIR /app

    RUN

    RUN 用于容器内部执行命令。每个 RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化。一般格式为 RUN <command> 。例如我们要安装 python 依赖包,我们做法如下:

    RUN pip install -r requirements.txt

    EXPOSE

    EXPOSE 命令用来指定对外开放的端口。一般格式为 EXPOSE <port> [<port>...]

    例如上面那个例子,开放5000端口:

    EXPOSE 5000

    ENTRYPOINT

    ENTRYPOINT 可以让你的容器表现得像一个可执行程序一样。一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。

    ENTRYPOINT 命令也有两种格式:

    • ENTRYPOINT ["executable", "param1", "param2"] :推荐使用的 exec形式
    • ENTRYPOINT command param1 param2 :shell 形式

    例如下面这个,我们要将 python 镜像变成可执行的程序,我们可以这样去做:

    ENTRYPOINT ["python"]

    CMD

    CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件。不包含可执行文件的情况下就要用 ENTRYPOINT 指定一个,然后 CMD 命令的参数就会作为ENTRYPOINT的参数。

    CMD 命令有三种格式:

    • CMD ["executable","param1","param2"]:推荐使用的 exec 形式。
    • CMD ["param1","param2"]:无可执行程序形式
    • CMD command param1 param2:shell 形式。

    一个 Dockerfile 中只能有一个CMD,如果有多个,则最后一个生效。而 CMD 的 shell 形式默认调用 /bin/sh -c 执行命令。

    CMD 命令会被 Docker 命令行传入的参数覆盖:docker run busybox /bin/echo Hello Docker 会把 CMD 里的命令覆盖。

    例如我们要启动 /app ,我们可以用如下命令实现:

    CMD ["app.py"]

    当然还有一些其他的命令,我们在用到的时候再去一一讲解一下。

    构建Dockerfile

    我们大体已经把Dockerfile的写法讲述完毕,我们可以自己动手写一个例子:

    mkdir static_web
    cd static_web
    touch Dockerfile
    然后 vi Dockerfile  开始编辑该文件
    输入 i 开始编辑
    
    以下是我们构建的Dockerfile内容
    ``````````
    FROM nginx
    MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>
    RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
    ``````````
    
    编辑完后 按 esc 退出编辑
    然后  :wq    写入 退出

    我们在 Dockerfile 文件所在目录执行:

    docker build -t angelkitty/nginx_web:v1 .

    我们解释一下, -t 是为新镜像设置仓库和名称,其中 angelkitty 为仓库名, nginx_web 为镜像名, :v1 为标签(不添加为默认 latest )

    我们构建完成之后,使用 docker images 命令查看所有镜像,如果存在 REPOSITORY 为 nginx 和 TAG 是 v1 的信息,就表示构建成功。

    接下来使用 docker run 命令来启动容器

    docker run --name nginx_web -d -p 8080:80   angelkitty/nginx_web:v1

    这条命令会用 nginx 镜像启动一个容器,命名为 nginx_web ,并且映射了 8080 端口,这样我们可以用浏览器去访问这个 nginx 服务器:http://localhost:8080/ 或者 http://本机的IP地址:8080/,页面返回信息:

    hello-docker

    这样一个简单使用 Dockerfile 构建镜像,运行容器的示例就完成了!

    来源:https://www.cnblogs.com/ECJTUACM-873284962/p/9789130.html

    展开全文
  • Docker——入门实战

    万次阅读 多人点赞 2018-07-14 15:35:24
    Docker 简介 Docker是一种新兴的虚拟化技术,能够一定程度上的代替传统虚拟机。不过,Docker 跟传统的虚拟化方式相比具有众多的优势。我也将Docker类比于Python虚拟环境,可以有效的配置各个版本的开发环境,...

    I. Docker

    简介

    Docker是一种新兴的虚拟化技术,能够一定程度上的代替传统虚拟机。不过,Docker 跟传统的虚拟化方式相比具有众多的优势。我也将Docker类比于Python虚拟环境,可以有效的配置各个版本的开发环境,比如深度学习与Java环境。

    其他的Docker简介也不需要过多介绍,可以参考很流行的《Docker — 从入门到实践》。关于博客,文末列出了最近在掘金上看到的一些入门类型文章。

    优势

    本人主要想用来配置开发环境,由于实验室机器系统环境版本等冲突的问题。

    先用一张Docker — 从入门到实践里的图整体感受一下其独特的优势:

    对比传统虚拟机

    由于本人才疏学浅,这里便再节选一些原文中话具体描述Docker强大所在。个人感觉在入门完Docker再回头重新认识一下下面所述的五个优势相关解释,会对Docker的认识有更深的理解。

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

    II. Docker中基本概念

    镜像(Image)

    镜像,从认识上简单的来说,就是面向对象中的类,相当于一个模板。从本质上来说,镜像相当于一个文件系统。Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。

    容器(Container)

    容器,从认识上来说,就是类创建的实例,就是依据镜像这个模板创建出来的实体。容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。

    仓库(Repository)

    仓库,从认识上来说,就好像软件包上传下载站,有各种软件的不同版本被上传供用户下载。镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

    Docker版本

    Docker 划分为CE 和EE。CE 即社区版(免费,支持周期三个月),EE 即企业版,强调安全,付费使用。Docker在1.13 版本之后,从2017年的3月1日开始,版本命名规则变为如下:

    项目 说明
    版本格式 YY.MM
    Stable版本 每个季度发行
    Edge版本 每个月发型

    Docker CE 每月发布一个Edge 版本(17.03, 17.04, 17.05…),每三个月发布一个Stable 版本(17.03, 17.06, 17.09…),Docker EE 和Stable 版本号保持一致,但每个版本提供一年维护。

    分层存储

    因为镜像包含操作系统完整的root 文件系统,其体积往往是庞大的,因此在Docker设计时,就充分利用Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成

    镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

    分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

    III. 安装Docker

    Win10

    下载:https://docs.docker.com/docker-for-windows/install/

    Docker支持64 位版本的Windows 10 Pro,且必须开启Hyper-V。开启方式为:打开“控制面板”->“程序”-> “启动或关闭Windows功能”,找到Hyper-V并勾选,确定重启电脑。

    开启Hyper-V

    安装下载好的Docker for Windows Installer.exe,如下:

    安装完毕

    鉴于国内网络问题,后续拉取Docker镜像十分缓慢,需要配置国内镜像加速,在系统右下角托盘Docker 图标内右键菜单选择Settings,打开配置窗口后左侧导航菜单选择Daemon,在Registry mirrors 一栏中填写加速器地址
    https://registry.docker-cn.com ,之后点击Apply保存后Docker就会重启并应用配置的镜像地址了。

    配置镜像加速

    Ubuntu16.04+

    在Ubuntu系统中安装较为简单,官方提供了脚本供我们进行安装。

    sudo apt install curl
    curl -fsSL get.docker.com -o get-docker.sh
    sudo sh get-docker.sh --mirror Aliyun

    执行这个命令后,脚本就会自动的将一切准备工作做好,并且把Docker CE 的Edge版本安装在系统中。

    启动Docker CE

    sudo systemctl enable docker
    sudo systemctl start docker

    建立docker 用户组

    默认情况下,docker 命令会使用Unix socket 与Docker 引擎通讯。而只有root 用户和docker 组的用户才可以访问Docker 引擎的Unix socket。出于安全考虑,一般Ubuntu系统上不会直接使用root 用户。因此,更好地做法是将需要使用docker 的用户加入docker用户组。

    # 建立docker组
    sudo groupadd docker
    # 将当前用户加入docker组
    sudo usermod -aG docker $USER

    注销当前用户,重新登录Ubuntu,输入docker info,此时可以直接出现信息。

    docker info

    配置国内镜像加速

    在/etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件)

    {
        "registry-mirrors": [
            "https://registry.docker-cn.com"
        ]
    }

    重新启动服务

    sudo systemctl daemon-reload
    sudo systemctl restart docker

    IV. Docker的C/S模式

    Docker 采用了C/S 架构,包括客户端和服务端。Docker 守护进程(Daemon)作为服务端
    接受来自客户端的请求,并处理这些请求(创建、运行、分发容器)。

    Docker基本架构

    Docker 守护进程一般在宿主主机后台运行,等待接收来自客户端的消息;Docker 客户端则为用户提供一系列可执行命令,用户用这些命令实现跟Docker 守护进程交互。我们之前在Win10的命令行中便是最主要的客户端:

    Docker也为我们提供了Remote API来操作Docker的守护进程,也意味着我们可以通过自己的程序来控制Docker的运行。客户端和服务端既可以运行在一个机器上,也可通过socket 或者RESTful API 来进行通信:

    至于Docker的客户端与守护进程之间的通信,其连接方式为socket连接。主要有三种socket连接方式:

    • unix:///var/run/docker.sock
    • tcp://host:port
    • fd://socketfd

    完整的Docker的C/S连接方式的本质可以一般表示为如下:

    V. 使用Docker

    容器的基操

    • 启动一次操作容器docker run IMAGE_NAME [COMMAND] [ARG…]

      例如,启动一个容器输出hello world。由于刚装上Docker,没有任何镜像,所以会先下载一个最新的ubuntu18.04的docker镜像。一次操作容器在处理完操作后会立即关闭容器。

      docker run ubuntu echo 'hello world'

      启动一次操作容器

    • 启动交互式容器docker run -t -i –name=自定义名称 IMAGE_NAME /bin/bash

      -i –interactive=true | false,默认是false

      -t –tty=true | false,默认是false

      –name 给启动的容器自定义名称,方便后续的容器选择操作

      启动交互式的容器,就是类似虚拟机、云主机的操作方式,操作完一个命令后仍然可以继续

      docker run -i -t ubuntu /bin/bash

      启动交互式容器

    • 查看容器docker ps [-a] [-l]

      省略 列出正在运行的容器

      -a all 列出所有容器

      -l latest 列出最近的容器

      查看所有容器

    • 查看指定容器docker inspect name | id

      name指代具体的容器名称,id则是容器的唯一id标识。inspect命令可以详细的展示出容器的具体信息。

      docker inspect haha

      查看指定容器

    • 重新启动停止的容器docker start [-i] 容器名

      实际使用时,没必要每次都重新启动一个新的容器,我们可以重新启动之前创建的容器,现实情况也需要我们这样使用。

      docker start -i haha

      重启停止的容器

    • 删除停止的容器docker rm name | id

      docker rm thirsty_kepler
      docker rm upbeat_albattani

      删除停止的容器

    守护式容器

    交互式容器在运行完命令退出后即停止,而实际中我们常常需要能够长时间运行,即使退出也能后台运行的容器,而守护式容器具备这一功能。守护式容器具有:

    1. 能够长期运行;
    2. 没有交互式会话;
    3. 适合于运行应用程序和服务。

    以守护形式运行容器

    我们执行完需要的操作退出容器时,不要使用exit退出,可以利用Ctrl+P Ctrl+Q代替,以守护式形式推出容器。

    守护形式运行容器

    附加到运行中的容器

    退出正在运行的容器,想要再次进入,需要使用attach命令:docker attach name | id

    docker attach haha

    启动守护式容器

    启动守护式容器,可以在后台为我们执行操作:docker run -d IMAGE_NAME [COMMAND] [ARG…]

    当命令在后台执行完毕,容器还是会关闭。这里防止容器立刻退出,写一个脚本循环输出“hello world”。

    docker run --name hiahia -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"

    启动守护式容器

    查看容器日志

    当守护式容器在后台运行时,我们可以利用docker的日志命令查看其输出:docker logs [-f] [-t] [–tail] IMAGE_NAME

    -f –follows=true | false,默认是false,显示更新

    -t –timestamps=true | false,默认是false,显示时间戳

    –tail=“all” | 行数,显示最新行数的日志

    查看容器日志

    查看容器内进程

    对运行的容器查看其进程:docker top IMAGE_NAME

    查看容器内进程

    运行中容器启动新进程

    Docker的理念是一个容器运行一个服务,但是往往需要对一个服务进行监控,所以也需要在已经运行服务的容器启动新的进程:docker exec [-d] [-i] [-t] IMAGE_NAME [COMMAND] [ARG…]

    docker exec -i -t hiahia /bin/bash

    启动新进程

    停止守护式容器

    发送信号停止容器:docker stop 容器名

    强制停止:docker kill 容器名

    VI. 案例:在容器中部署静态网站

    容器的端口映射

    命令run [-P] [-p]

    -P,–publish-all=true | false,大写的P表示为容器暴露的所有端口进行映射;

    -p,–publish=[],小写的p表示为容器指定的端口进行映射,有四种形式:

    • containerPort:只指定容器的端口,宿主机端口随机映射;
    • hostPort:containerPort:同时指定容器与宿主机端口一一映射;
    • ip::containerPort:指定ip和容器的端口;
    • ip:hostPort:containerPort:指定ip、宿主机端口以及容器端口。

    例如:

    docker run -p 80 -i -t ubuntu /bin/bash
    docker run -p 8080:80 -i -t ubuntu /bin/bash
    docker run -p 0.0.0.0::80 -i -t ubuntu /bin/bash
    docker run -p 0.0.0.0:8080:80 -i -t ubuntu /bin/bash

    容器中部署Nginx服务

    准备环境:

    # 1. 创建映射80端口的交互式容器
    docker run -p 80 --name web -i -t ubuntu /bin/bash
    # 2. 更新源
    apt-get update
    # 3. 安装Nginx
    apt-get install -y nginx
    # 4. 安装Vim
    apt-get install -y vim

    创建静态页面:

    mkdir -p /var/www/html
    cd /var/www/html
    vim index.html

    index.html

    修改Nginx配置文件:

    # 查看Nginx安装位置
    whereis nginx
    # 修改配置文件
    vim /etc/nginx/sites-enabled/default

    修改Nginx配置文件

    运行Nginx:

    # 启动nginx
    nginx
    # 查看进程
    ps -ef

    运行Nginx

    验证网站访问:

    # 退出容器
    Ctrl+P Ctrl+Q
    # 查看容器进程
    docker top web
    # 查看容器端口映射情况
    docker port web

    查看进程和端口

    通过宿主机地址加映射端口访问:

    访问网站

    VII. 镜像基操

    查看删除镜像

    • 列出镜像docker images [OPTIONS] [REPOSITORY]

      -a,–all=false,显示所有镜像

      -f,–filter=[],显示时过滤条件

      –no-trunc=false,指定不使用截断的形式显示数据

      -q,–quiet=false,只显示镜像的唯一id

      查看镜像

    • 查看镜像docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE]

      -f,–format=“”

      查看镜像

    • 删除镜像docker rmi [OPTIONS] IMAGE [IMAGE]

      -f,–force=false,强制删除镜像

      –no-prune=false,保留未打标签的父镜像

    • 虚悬镜像:既没有仓库名,也没有标签,均为\

    获取推送镜像

    • 查找镜像docker search [OPTIONS] TEAM

      –automated=false,仅显示自动化构建的镜像

      –no-trunc=false,不以截断的方式输出

      –filter,添加过滤条件

      查找ubuntu镜像

    • 拉取镜像docker pull [OPTIONS] NAME [:TAG]

      -a,–all-tags=false,下载所有的镜像(包含所有TAG)

      拉取镜像

    • 推送镜像:docker push NAME [:TAG]

      Docker允许上传我们自己构建的镜像,需要注册DockerHub的账户。也可以上传到阿里云,地址:https://cr.console.aliyun.com/#/namespace/index

    构建镜像

    构建Docker镜像,可以保存对容器的修改,并且再次使用。构建镜像提供了自定义镜像的能力,以软件的形式打包并分发服务及其运行环境。Docker中提供了两种方式来构建镜像:

    • 通过容器构建:docker commit
    • 通过Dockerfile:docker build

    使用commit命令构建镜像

    命令:docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

    参数:-a,–author=“”,指定镜像的作者信息

    ​ -m,–message=“”,提交信息

    ​ -p,–pause=true,commit时是否暂停容器

    commit命令构建镜像

    使用Dockerfile文件构建镜像

    Docker允许我们利用一个类似配置文件的形式来进行构建自定义镜像,在文件中可以指定原始的镜像,自定义镜像的维护人信息,对原始镜像采取的操作以及暴露的端口等信息。比如:

    # Sample Dockerfile
    FROM ubuntu:16.04
    MAINTAINER wgp "Kingdompin@163.com"
    RUN apt-get update
    RUN apt-get install -y nginx
    EXPOSE 80

    命令:docker build [OPTIONS] DockerFile_PATH | URL | -

    参数:–force-rm=false

    ​ –no-cache=false

    ​ –pull=false

    ​ -q,quite=false,构建时不输出信息

    ​ –rm=true

    ​ -t,tag=“”,指定输出的镜像名称信息

    Dockerfile文件构建镜像

    VIII. 镜像迁移

    我们制作好的镜像,一般会迁移或分享给其他需要的人。Docker提供了几种将我们的镜像迁移、分享给其他人的方式。推荐镜像迁移应该直接使用Docker Registry,无论是直接使用Docker Hub还是使用内网私有Registry都可以。使用镜像频率不高,镜像数量不多的情况下,我们可以选择以下两种方式。

    上传Docker Hub

    首先,需要在Docker Hub上申请注册一个帐号(人机验证时需要科学上网)。然后我们需要创建仓库,指定仓库名称。

    新建仓库

    在终端中登录你的Docker Hub账户,输入docker login,输入用户名密码即可登录成功。

    登录docker账户

    查看需要上传的镜像,并将选择的镜像打上标签,标签名需和Docker Hub上新建的仓库名称一致,否则上传失败。给镜像打标签的命令如下。

    docker tag <existing-image> <hub-user>/<repo-name>[:<tag>]

    其中existing-image代表本地待上传的镜像名加tag,后面<hub-user>/<repo-name>[:<tag>]则是为上传更改的标签名,tag不指定则为latest。

    打上标签

    可以看到,我们重新为ubuntu:16.04的镜像打上标签,观察IMAGE ID可知,同一镜像可以拥有不同的标签名。接下来,我们利用push命令直接上传镜像。

    docker push <hub-user>/<repo-name>:<tag>

    如图,我们已经上传成功。由于之前介绍的分层存储系统,我们这里是直接对已有的ubuntu镜像进行上传,只是重新打了标签,所以真正上传的只是变化的部分。

    上传成功

    Hub查看

    导出文件互传

    Docker 还提供了 docker loaddocker save 命令,用以将镜像保存为一个tar文件。比如这次我们将ubuntu:latest这个镜像保存为tar文件。

    docker save

    查看本地磁盘,即可看见名为ubuntu18.04的tar包。我们可以将其拷贝给其他PC,利用load命令重新导入。

    重新导入镜像

    推荐阅读

    展开全文
  • 1.下载docker安装文件。 地址:https://download.docker.com/linux/static/stable/x86_64/ 我下载的版本是docker-18.06.3-ce.tgz 2.上传docker到服务器 以使用putty为例子。 打开putty目录下的psFTP。输入...

    1.下载docker安装文件。

        地址:https://download.docker.com/linux/static/stable/x86_64/

        我下载的版本是docker-18.06.3-ce.tgz

    2.上传docker到服务器

        以使用putty为例子。

        打开putty目录下的psFTP。输入以下命令:

    #输入linux的地址
    open 192.168.3.237
    #输入登录的用户/密码
    
    #复制文件,前面是windows中的地址,后面是linux中的地址
    put C:/Users/e490/Downloads/docker-18.06.3-ce.tgz /usr/local/docker-18.06.3-ce.tgz
    
    #等待上传完成。

    3.安装docker服务 

    进入linux服务器。

    #进入dokcer上传的目录:/usr/lcoal
    cd /usr/local
    #解压到当前目录
    tar -zxvf docker-18.06.3-ce.tgz
    #复制到/user/bin
    cp docker/* /usr/bin/

    将docker注册为服务,

    vim /etc/systemd/system/docker.service

     内容为:

    [Unit]
    
    Description=Docker Application Container Engine
    
    Documentation=https://docs.docker.com
    
    After=network-online.target firewalld.service
    
    Wants=network-online.target
    
    [Service]
    
    Type=notify
    
    # the default is not to use systemd for cgroups because the delegate issues still
    
    # exists and systemd currently does not support the cgroup feature set required
    
    # for containers run by docker
    
    ExecStart=/usr/bin/dockerd
    
    ExecReload=/bin/kill -s HUP $MAINPID
    
    # Having non-zero Limit*s causes performance problems due to accounting overhead
    
    # in the kernel. We recommend using cgroups to do container-local accounting.
    
    LimitNOFILE=infinity
    
    LimitNPROC=infinity
    
    LimitCORE=infinity
    
    # Uncomment TasksMax if your systemd version supports it.
    
    # Only systemd 226 and above support this version.
    
    #TasksMax=infinity
    
    TimeoutStartSec=0
    
    # set delegate yes so that systemd does not reset the cgroups of docker containers
    
    Delegate=yes
    
    # kill only the docker process, not all processes in the cgroup
    
    KillMode=process
    
    # restart the docker process if it exits prematurely
    
    Restart=on-failure
    
    StartLimitBurst=3
    
    StartLimitInterval=60s
    
     
    
    [Install]
    
    WantedBy=multi-user.target

    4.启动docker 

    #赋予权限
    chmod +x /etc/systemd/system/docker.service 
    #重载unit配置文件
    systemctl daemon-reload
    #启动Docker
    systemctl start docker
    #设置开机自启
    systemctl enable docker.service  
    

    5.检查docker

    #查看Docker状态
    systemctl status docker                                                         
    #查看Docker版本
    docker -v                                                                                     

    参考文章:https://www.cnblogs.com/luoSteel/p/10038954.html 

     

    6.下载docker-compose文件

    地址:https://github.com/docker/compose/releases

    下载这个docker-compose-Linux-x86_64

    7.上传docker-compose到服务器

        以使用putty的psFTP 为例子。

       把文件的名字改成docker-compose,直接上传到/usr/bin

    #输入linux的地址
    open 192.168.3.237
    #输入登录的用户/密码
    
    #复制文件,前面是windows中的地址,后面是linux中的地址
    put C:/Users/e490/Downloads/docker-compose /usr/bin/docker-compose
    

    8.授权与测试 

    #授权
    chmod +x docker-compose
    #测试
    docker-compose -v
    

     

    docker与docker-compose的离线安装就完成了 

     

    展开全文
  • docker-compose离线安装

    2020-06-23 14:22:31
    一直使用在线安装docker-compose,一直有很多坑,今天有个哥们(人才)使用了离线安装compose 我尝试了一下 很方便 下载地址: https://github.com/docker/compose/releases 下载离线包 sudo mv docker-compose-...
  • Docker离线安装 安装 2+8+2 个依赖 一 分别安装 2个依赖 docker-ce-cli-18.09.8-3.el7.x86_64.rpm containerd.io-1.2.2-3.el7.x86_64.rpm [root@localhost docker]# rpm -ivh docker-ce-cli-18.09.8-3.el7.x86_64....
  • 离线安装docker-compose

    2020-07-15 17:25:12
    安装docker-compose,因为连不了外网,使用命令在线下载安装: sudo curl -L “https://github.com/docker/compose/releases/download/1.24.1/docker-compose-(uname−s)−(uname -s)-(uname−s)−(uname -m)” -o /...
  • docker & docker-compose离线安装以及部署

    千次阅读 2019-09-10 11:35:57
    docker-17.12.1-ce 安装docker 官方提供了docker打包后的文件,我们直接使用即可。 下载地址:https://download.docker.com/linux/static/stable/x86_64/ 自行选择相应的版本(注意:1.docke...
  • Docker教程-安装

    千次阅读 2020-02-25 14:50:23
    介绍Docker在不同平台上的安装。
  • 这可能是最为详细的Docker入门总结

    千次阅读 多人点赞 2018-11-14 07:44:00
    在计算机技术日新月异的今天, Docker 在国内发展的如火如荼。特别是在一线互联网公司 Docker 的使用是十分普遍的,甚至成为了一些企业面试的加分项,不信的话看看下...
  • 宋宝华:Docker 最初的2小时(Docker从入门到入门)

    万次阅读 多人点赞 2017-02-21 09:42:31
    最初的2小时,你会爱上Docker,对原理和使用流程有个最基本的理解,避免满世界无头苍蝇式找资料。本人反对暴风骤雨式多管齐下狂轰滥炸的学习方式,提倡迭代学习法,就是先知道怎么玩,有个感性认识,再深入学习高级...
  • docker

    万次阅读 多人点赞 2017-12-05 17:36:29
    应用场景 给你一台笔记本,笔记本的系统是windows的,如果想使用linux系统,那么得在...如果用了docker技术,那么就可以建成千上万个docker容器,一个docker容器就相当于一个linux虚拟机,它可以将计算机资源利用
  • docker入门(利用docker部署web应用)

    万次阅读 多人点赞 2019-05-26 10:44:15
    前言:本课程是在慕课网上学习 第一个docker化的java应用 课程时所做的笔记,供本人复习之用 目录 第一章 什么是docker 1.1 docker的发展史 1.2 docker国内应用史 1.3 什么是Docker 第二章 了解docker 2.1 ...
  • docker-compose教程(安装,使用, 快速入门)

    万次阅读 多人点赞 2017-12-03 22:31:45
    教程基于ubuntu下最新的...Docker Compose是一个用来定义和运行复杂应用的Docker工具。一个使用Docker容器的应用,通常由多个容器组成。使用Docker Compose不再需要使用shell脚本来启动容器。 Compose 通过一个配...
  • 使用YUM 安装 docker

    万次阅读 2019-10-22 09:10:25
    第一步:查看系统内核(内核3.10以上 ) 如下图所示: 如果版本在Centos 7.0以上就可以了。 查看当前系统内核版本的命令如下: ...第二步:清理已经安装的docker(如果没有安装过,可以跳过此步) 清理...
  • docker命令

    万次阅读 2017-12-06 11:42:36
    应用场景 docker使用的时候,有自己一套专业的...1. 镜像: # docker pull 镜像名 (下载镜像) # docker run -t -i 镜像名 /bin/bash (利用镜像创建一个容器,在其中运行bash) # docker images (查看镜像,repositor
  • docker服务启动,重启,关闭命令

    万次阅读 多人点赞 2018-05-26 18:16:50
    最近刚学习dockerdocker启动命令,docker重启命令,docker关闭命令启动 systemctl start docker守护进程重启 sudo systemctl daemon-reload重启docker服务 systemctl restart docker重启docker服务 sudo service ...
  • Docker

    万次阅读 多人点赞 2019-10-29 23:15:26
    文章目录@[toc]dockerdocker 手册centos7 联网安装docker官方安装手册镜像加速基本概念镜像容器docker 镜像操作下载 CentOS 镜像查看centos7镜运行 centos7删除镜像镜像导出镜像导入容器操作启动容器后台运行查看...
  • docker-compose详解

    万次阅读 多人点赞 2019-02-18 11:06:19
    1 安装: 官方: curl -L ...chmod +x /usr/local/bin/docker-compose 或者使用包管理工具:...
1 2 3 4 5 ... 20
收藏数 488,889
精华内容 195,555
关键字:

docker