Docker入阶

网友投稿 598 2022-05-30

docker现在是Github社区最火开源项目之一,它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。docker 的基础是 Linux 容器(LXC)等技术。在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。

举个货物运输的例子。在1960年之前,大部分货物运输的过程中,托运人和搬运工都会担心不同类型的货物之间会发生互相损坏(比如:一堆铁锹在运输时,有可能倒下压坏同时在运输的一袋香蕉)。同样的,将不同货品做分类的运输也是非常痛苦的一件事情。有些需要被转运的货物在运输途中,会在一个港口卸下来,等待相同类型的货物一起重新装到指定的火车、货车或者其他运输工具上。一路上,很多货物被损坏,也有很多的货物被偷盗。不同的运输机制和不同的货物组成了一个N乘N的矩阵。

幸运的是,这个问题已经解决,一个标准化的运输集装箱可以解决这个问题。任何类型的货物,不管是开心果,还是保时捷。都能被集中打包放入一个标准的运输集装箱内。这个集装箱在运输途中是封闭不可以打开的,直到将它运输到目的地。这整个集装箱看做一个个体,装载,卸下,堆放,运输,有效的解决长距离的运输带来的问题。在运输过程中,从轮船到火车,再到卡车,都可以通过起重机(吊车),形成流程自动化。不需要管集装箱里面的东西。

在代码方面Docker就类似于这里的货物集装箱综合运输系统。Docker 能让任何的应用和它的依赖打包成为一个轻量级的、便携的、独立的一个集装箱。集装箱有标准的运作模式,因此可以方便自动化。他们被设计成能跑在几乎所有LINUX服务器上的容器。一个开发者在笔记本上建立和测试的一个Docker容器,能跑在测试环境、生产环境、虚拟机、新买的服务器、OpenStack集群、公共环境、或者是以上的组合的服务器群上。

物理集装箱

Docker

集装箱几乎支持所有类型的货物

能压缩任何负载和依赖

标准化的尺寸和交接使得集装箱可以通过货船火车货车运输,用起重机交接不需要换一个容器或者打开集装箱

使用操作系统的基本体(像LXC)能一致的跑在几乎任何硬件下,不需要对硬件做额外的修改

不需要关心铁锹会砸坏香蕉。集装箱可以一起堆放一起运输

资源、网络和内容的独立避免了依赖问题

标准化使得自动化装载卸货和移动变得方便

使用标准的操作指令去运行。对运营人员:CI、CD、自动化测试更为便捷,一键式操作

不需要打开不需要改动什么,高效的点对点的方式

轻量级,几乎没有启动的消耗,高效的移植性和操控性

发货人只需要关心箱子内部的事情,托运人只需要关心箱子外部的东西

开发者只需要关心代码层面,运营人员只需要关心服务器的基础环境

换句话说,开发者可以搭建他们的应用仅仅一次,就能保证让这个应用保持一致的跑在任何地方。运营人员可以将他们的服务器配置一遍,就能跑任何应用。

区别这两者的关键是,两者的底层架构是完完全全不同的。容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统虚拟机(像VMWare/KVM/Xen?EC2)通过硬件虚拟化来创造一整个虚拟系统。每一个虚拟机内的应用不仅仅包含这个应用的一些类库代码(这个应用可能只有10几M),而且还包含一整个操作系统。

除了底层架构的差别,相比之下Docker容器相会显的更便捷、高效。在传统的虚拟机,每一个应用,每一个应用的副本,和一个应用要求的轻微的修改都要求重新创造一整个新的虚拟机。其实有时候一个新应用,仅仅需要这个应用和它的文件/类库,并不需要新的操作系统。 如果你想在一台主机上跑几个这个应用的副本,你甚至不需要复制已经被分享的这些文件。 最后,如果你的应用有修改,你只需要将不同的地方复制过来。正如下图描述的,如果Docker的镜像有修改,你往往不是修改整个的镜像,只需要更新和原版本不同的东西。

4、为什么要使用 Docker?

作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。

首先,Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。

其次,Docker 对系统资源的利用率很高,一个单机计算机所支持的容器数量比虚拟机数量要多得多,一般为十倍以上的差距。

容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。

具体说来,Docker 在如下几个方面具有较大的优势。

更快速的交付和部署

对开发和运维(devop)人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。

开发者可以使用一个标准的镜像来构建一套开发容器,开发完成之后,运维人员可以直接使用这个容器来部署代码。 Docker 可以快速创建容器,快速迭代应用程序,并让整个过程全程可见,使团队中的其他成员更容易理解应用程序是如何创建和工作的。 Docker 容器很轻很快!容器的启动时间是秒级的,大量地节约开发、测试、部署的时间。

更高效的虚拟化

Docker 容器的运行不需要额外的 hypervisor 支持,它是内核级的虚拟化,因此可以实现更高的性能和效率。

更轻松的迁移和扩展

Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。 这种兼容性可以让用户把一个应用程序从一个平台直接迁移到另外一个。

更简单的管理

使用 Docker,只需要小小的修改,就可以替代以往大量的更新工作。所有的修改都以增量的方式被分发和更新,从而实现自动化并且高效的管理。

Docker使用客户端-服务器(client-server)架构模式。Docker客户端会与Docker守护进程进行通信。Docker守护进程会处理复杂繁重的任务,例如建立、运行、发布你的Docker容器。Docker客户端和守护进程可以运行在同一个系统上,当然你也可以使用Docker客户端去连接一个远程的Docker守护进程。Docker客户端和守护进程之间通过socket或者RESTful API进行通信。

下面介绍一下docker包括的三个基本概念:

Ø  镜像(Image)

Ø  容器(Container)

Ø  仓库(Repository)

1.         images(镜像)

Docker 镜像就是一个只读的模板。例如,一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了 Apache 或用户需要的其它应用程序。

镜像可以用来创建 Docker 容器。

Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。

2.         container(容器)

Docker 利用容器来运行应用。容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。

镜像是只读的,容器在启动的时候创建一层可写层作为最上层。

3.         repository(仓库)

仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。

仓库分为公开仓库(Public)和私有仓库(Private)两种形式。

最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括:时速云、网易云等,可以提供大陆用户更稳定快速的访问。当然,用户也可以在本地网络内创建一个私有仓库(参考“nexus 3.0 Private Registry for Docker”一文)。当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上pull下来就可以了。Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。

根据自己的理解,总的来说分为以下几种:

容器生命周期管理 — docker [run|start|stop|restart|kill|rm|pause|unpause]

容器操作运维 — docker [ps|inspect|top|attach|events|logs|wait|export|port]

容器rootfs命令 — docker [commit|cp|diff]

镜像仓库 — docker [login|pull|push|search]

本地镜像管理 — docker [images|rmi|tag|build|history|save|import]

其他命令 — docker [info|version]

可以通过这张图对docker的常用命令有个概括的了解。

1. 列出机器上的镜像(images)

# docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

ubuntu 14.10 2185fd50e2ca 13 days ago 236.9 MB

其中我们可以根据REPOSITORY来判断这个镜像是来自哪个服务器,如果没有 / 则表示官方镜像,类似于username/repos_name表示Github的个人公共库,类似于regsistory.example.com:5000/repos_name则表示的是私服。IMAGE ID列其实是缩写,要显示完整则带上--no-trunc选项。

2. 在docker index中搜索image(search)

Usage: docker search TERM

# docker search seanlo

NAME DESCRIPTION STARS OFFICIAL AUTOMATED

seanloook/centos6 sean's docker repos 0

搜索的范围是官方镜像和所有个人公共镜像。NAME列的 / 后面是仓库的名字。

Docker入阶

3. 从docker registry server 中下拉image或repository(pull)

Usage: docker pull [OPTIONS] NAME[:TAG]

# docker pull centos

上面的命令需要注意,在docker v1.2版本以前,会下载官方镜像的centos仓库里的所有镜像,而从v.13开始官方文档里的说明变了,只会下载tag为latest的镜像(以及同一images id的其他tag)。

如果你没有网络,或者从其他私服获取镜像,形如docker pull registry.domain.com:port/repos:

# docker pull   dl.dockerpool.com:5000/mongo:latest

4. 推送一个image或repository到registry(push)

与上面的pull对应,可以推送到Docker Hub的Public、Private以及私服,但不能推送到Top Level Repository。

# docker push seanlook/mongo

# docker push registry.tp-link.net:5000/mongo:2014-10-27

registry.tp-link.net也可以写成IP,172.29.88.222。

在repository不存在的情况下,命令行下push上去的会为我们创建为私有库,然而通过浏览器创建的默认为公共库.

5. 从image启动一个container(run)

docker run命令首先会从特定的image创之上create一层可写的container,然后通过start命令来启动它。停止的container可以重新启动并保留原来的修改。run命令启动参数有很多。

1) 使用image创建container并进入交互模式, login shell是/bin/bash

# docker run -i -t --name mytest centos:centos6 /bin/bash

bash-4.1#

上面的--name参数可以指定启动后的容器名字,如果不指定则docker会帮我们取一个名字。镜像centos:centos6也可以用IMAGE ID (68edf809afe7) 代替),并且会启动一个伪终端,但通过ps或top命令我们却只能看到一两个进程,因为容器的核心是所执行的应用程序,所需要的资源都是应用程序运行所必需的,除此之外,并没有其它的资源,可见Docker对资源的利用率极高。此时使用exit或Ctrl+D退出后,这个容器也就消失了(消失后的容器并没有完全删除)

2) 运行出一个container放到后台运行

# docker run -d ubuntu /bin/sh -c "while   true; do echo hello world; sleep 2; done"

ae60c4b64205

它将直接把启动的container挂起放在后台运行(这才叫saas),并且会输出一个CONTAINER ID,通过docker ps可以看到这个容器的信息,可在container外面查看它的输出docker logs ae60c4b64205,也可以通过docker attach ae60c4b64205连接到这个正在运行的终端,此时在Ctrl+C退出container就消失了,按ctrl-p ctrl-q可以退出到宿主机,而保持container仍然在运行另外,如果-d启动但后面的命令执行完就结束了,如/bin/bash、echo test,则container做完该做的时候依然会终止。而且-d不能与–rm同时使用。

3)  映射host到container的端口和目录

映射主机到容器的端口是很有用的,比如在container中运行memcached,端口为11211,运行容器的host可以连接container的 internel_ip:11211 访问,如果有从其他主机访问memcached需求那就可以通过-p选项,形如-p ,存在以下几种写法:

-p 11211:11211 这个即是默认情况下,绑定主机所有网卡(0.0.0.0)的11211端口到容器的11211端口上

-p 127.0.0.1:11211:11211 只绑定localhost这个接口的11211端口

目录映射其实是“绑定挂载”host的路径到container的目录,这对于内外传送文件比较方便,为了避免私服container停止以后保存的images不被删除,就要把提交的images保存到挂载的主机目录下。使用比较简单,-v ,绑定多个目录时再加-v。

另外在两个container之间建立联系可用--link。

下面是一个例子:

# docker run --name nginx_test \

> -v /tmp/docker:/usr/share/nginx/html:ro \

> -p 80:80 -d \

> nginx:1.7.6

在主机的/tmp/docker下建立index.html,就可以通过http://localhost:80/或http://host-ip:80访问了。

6. 开启/停止/重启container(start/stop/restart)

容器可以通过run新建一个来运行,也可以重新start已经停止的container,但start不能够再指定容器启动时运行的指令,因为docker只能有一个前台进程。

容器stop(或Ctrl+D)时,会在保存当前容器的状态之后退出,下次start时保有上次关闭时更改。而且每次进入attach进去的界面是一样的,与第一次run启动或commit提交的时刻相同。

CONTAINER_ID=$(docker start )

docker stop $CONTAINER_ID

docker restart $CONTAINER_ID

7. 连接到正在运行中的container(attach)

要attach上去的容器必须正在运行,可以同时连接上同一个container来共享屏幕(与screen命令的attach类似)。

官方文档中说attach后可以通过CTRL-C来detach,但实际上经过我的测试,如果container当前在运行bash,CTRL-C自然是当前行的输入,没有退出;如果container当前正在前台运行进程,如输出nginx的access.log日志,CTRL-C不仅会导致退出容器,而且还stop了。这不是我们想要的,detach的意思按理应该是脱离容器终端,但容器依然运行。好在attach是可以带上--sig-proxy=false来确保CTRL-D或CTRL-C不会关闭容器。

# docker attach --sig-proxy=false $CONTAINER_ID

8. 删除一个或多个container、image(rm、rmi)

你可能在使用过程中会build或commit许多镜像,无用的镜像需要删除。但删除这些镜像是有一些条件的:

Ø  同一个IMAGE ID可能会有多个TAG(可能还在不同的仓库),首先你要根据这些 image names 来删除标签,当删除最后一个tag的时候就会自动删除镜像;

Ø  承上,如果要删除的多个IMAGE NAME在同一个REPOSITORY,可以通过docker rmi 来同时删除剩下的TAG;若在不同Repo则还是需要手动逐个删除TAG;

Ø  还存在由这个镜像启动的container时(即便已经停止),也无法删除镜像;

删除容器

docker rm

删除所有停止的容器

docker rm $(docker ps -a -q)

删除镜像

docker rmi

9. docker build 使用此配置生成新的image

build命令可以从Dockerfile和上下文来创建镜像:

docker build [OPTIONS] PATH | URL | -

上面的PATH或URL中的文件被称作上下文,build image的过程会先把这些文件传送到docker的服务端来进行的。

如果PATH直接就是一个单独的Dockerfile文件则可以不需要上下文;如果URL是一个Git仓库地址,那么创建image的过程中会自动git clone一份到本机的临时目录,它就成为了本次build的上下文。无论指定的PATH是什么,Dockerfile是至关重要的

FROM seanlook/nginx:bash_vim

EXPOSE 80

ENTRYPOINT /usr/sbin/nginx -c /etc/nginx/nginx.conf && /bin/bash

# docker build -t seanlook/nginx:bash_vim_Df .

Sending build context to Docker daemon 73.45 MB

Sending build context to Docker daemon

Step 0 : FROM seanlook/nginx:bash_vim

---> aa8516fa0bb7

Step 1 : EXPOSE 80

---> Using cache

---> fece07e2b515

Step 2 : ENTRYPOINT /usr/sbin/nginx -c /etc/nginx/nginx.conf && /bin/bash

---> Running in e08963fd5afb

---> d9bbd13f5066

Removing intermediate container e08963fd5afb

Successfully built d9bbd13f5066

面的PATH为.,所以在当前目录下的所有文件(不包括.dockerignore中的)将会被tar打包并传送到docker daemon(一般在本机),从输出我们可以到Sending build context...,最后有个Removing intermediate container的过程,可以通过--rm=false来保留容器。

10. 给镜像打上标签(tag)

tag的作用主要有两点:一是为镜像起一个容易理解的名字,二是可以通过docker tag来重新指定镜像的仓库,这样在push时自动提交到仓库。

将同一IMAGE_ID的所有tag,合并为一个新的

# docker tag 195eb90b5349   seanlook/ubuntu:rm_test

新建一个tag,保留旧的那条记录

# docker tag Registry/Repos:Tag   New_Registry/New_Repos:New_Tag

转载请注明出处:华为云博客 https://portal.hwclouds.com/blogs

Docker

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Elasticsearch实例cpu使用率高排查思路
下一篇:android 开发日积月累
相关文章