Docker风流史

引入

在生活中经常听到 Docker 这个词,但 Docker 到底是什么呐?此问题一出,致使很多人感到疑惑,Docker 不就是一个容器吗?类似的还有Tomcat、Jetty等,对此回答到底对不对呐,就请朋友们一起跟着我的脚步共同进入Docker的世界,一起来揭开 Docker 的庐山真面,看看 Docker 背后到底藏着什么 Secret(秘密)。

Docker是何物?

官方解读:
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。其口号–“一次创建,到处运行”。

个人经验总结:

  1. docker是一个开源的软件部署解决方案;
  2. docker也是轻量级的应用容器框架;
  3. docker可以打包、发布、运行任何的应用

Dcoker为何而生?

Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源。

1.看一下不使用Docker的开发部署几条缺点:

  • 资源利用率相对较低
  • 但物理机多应用无法有效隔离(如CPU、进程、磁盘)
  • 测试、版本管理复杂
  • 迁移成本高且较为麻烦
  • 传统虚拟机空间占用大、启动慢、管理复杂
  • 开发人员可以消除协作编码时“在我的机器上可正常工作”的问题。
  • 运维人员可以在隔离容器中并行运行和管理应用,获得更好的计算密度。

从上面不使用Docker开发部署的几条缺点可以看出Docker到底为何而生了吧,且也正好引出了Docker的优点所在。“鱼和熊掌不可得兼”这个道理大家应该都懂吧,所以说有长必有短,既然Docker有这么多的好处,那也必然有其局限之处。

井底之Docker

  1. Docker是基于Linux 64bit的,无法在32bit的linux/Windows/unix环境下使用
  2. LXC是基于cgroup等linux kernel功能的,因此container的guest系统只能是linux base的
  3. 隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库
  4. 网络管理相对简单,主要是基于namespace隔离
  5. cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是按内存收费)
  6. Docker对disk的管理比较有限
  7. container随着用户进程的停止而销毁,container中的log等用户数据不便收集

Docker vs VM

很多朋友分不清Docker容器与虚拟机的关系,老是混淆在一起。鉴于此就让我们一起看看其区别于联系吧

1、联系
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。
2、区别
找不同哦

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

传统虚拟机如 VMware , VisualBox 之类的需要模拟整台机器包括硬件,每台虚拟机都需要有自己的操作系统,虚拟机一旦被开启,预分配给它的资源将全部被占用。每一台虚拟机包括应用,必要的二进制和库,以及一个完整的用户操作系统。而容器技术是和我们的宿主机共享硬件资源及操作系统,可以实现资源的动态分配。容器包含应用和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在用户空间以分离的进程运行。从上面的图表中可以很直观的看出其区别。

Docker Install(安装)

注:在此只讲解Centos7及以上版本的系统安装,其他系统自行查资料进行安装使用。

1.升级yum:
    yum update
2.卸载旧版本:
    sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
3.安装Docker Engine-Community,在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库。之后,您可以从仓库安装和更新 Docker。

    a.安装所需的依赖
    sudo yum install -y yum-utils \
                      device-mapper-persistent-data \
                      lvm2

    b.设置稳定的仓库
    sudo yum-config-manager \
                    --add-repo \
                    https://download.docker.com/linux/centos/docker-ce.repo

    c.安装最新版本的 Docker
    sudo yum install docker-ce docker-ce-cli containerd.io

    注:如果提示您接受 GPG 密钥,请选是。
2.当然在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装:
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh

注:看到这是不是有一种想怒打作者的冲动,我费好大劲把上面的步骤走完了,你又说有简单的办法,这不是找打吗?哈哈。
3.验证是否安装成功

docker version
or
docker info
对此Docker就安装完成了,你是一脸懵逼不知所云,还是思路清晰跟着作者一步一步走下来了呐?

Docker三大概念及常用命令

1.启动Docker
sudo systemctl enable docker
sudo systemctl start docker

一图说天下

Docker常用命令

Docker架构

学习一门新知识不了解其内在架构,终究是过于浅敷,遇到棘手的问题很难从根本去思考。所以想学好Docker的小伙伴们就必须了解Docker的内在架构。

说事专用图

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

通过上图大致我们可以了解到,Docker 的核心组件包括:

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

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

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

其大致可分为三部分:

  • Docker Server

  • Engine

  • Job

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

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

  1. 向 Docker Registry 获取镜像
  2. 通过 graphdriver 执行容器镜像的本地化操作
  3. 通过 networkdriver 执行容器网络环境的配置
  4. 通过 execdriver 执行容器内部运行的执行工作
  5. 由于 Docker Daemon 和 Docker Client 的启动都是通过可执行文件 docker 来完成的,因此两者的启动流程非常相似。 Docker 可执行文件运行时,运行代码通过不同的命令行 flag 参数,区分两者,并最终运行两者各自相应的部分。

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

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

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

1、默认配置下,Docker daemon 只能响应来自本地 Host 的客户端请求。若想允许远程客户端请求,需要在配置文件中打开 TCP 监听。进行如下配置即可:

==编辑配置文件 /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 服务器的信息

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

镜像有多种生成方法:

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

也可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称作 Dockerfile ,通过执行 docker build 命令可以构建出 Docker 镜像

4、Docker Registry
Docker registry 是存储 docker image 的仓库,运行docker push、docker pull、docker search时,实际上是通过 docker daemon 与 docker registry 通信。如下图:

康康小课堂

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

Docker组件是如何协同工作支撑起容器的呐?

容器启动过程如下:

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

一起来看一下具体流程吧

运行容器
kang

查看镜像
kang

查看正在运行的容器
kang

上面步骤就是Docker运行一个容器的步骤,知道了这些再使用Docker命令是思路是不是清晰了许多。

Docker常用命令温故

Docker常用命令图示

DockerFile是何物

上面我们已经提到过DockerFile了,但它到底是何方神圣呐,带着疑问跟着我的步伐一起进入DockerFile的世界看看吧。

Dockerfile 是自动构建 docker 镜像的配置文件, 用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile 中的命令非常类似于 linux 下的 shell 命令。且Dockerfile 可以自定义镜像,通过 Docker 命令去运行镜像,从而达到启动容器的目的。

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

说事专用图

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

一般可以将 Dockerfile 分为四个部分:

  1. 基础镜像(父镜像)信息指令 FROM
  2. 维护者信息指令 MAINTAINER
  3. 镜像操作指令 RUN 、 EVN 、 ADD 和 WORKDIR 等
  4. 容器启动指令 CMD 、 ENTRYPOINT 和 USER 等
如下示例:

 1. FROM python:2.7
 2. MAINTAINER kang <1468140258@qq.com>
 3. COPY . /app
 4. WORKDIR /app
 5. RUN pip install -r requirements.txt
 6. EXPOSE 5000
 7. ENTRYPOINT ["python"]
 8. CMD ["app.py"]

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

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

到此一个容器就顺利起来了,你看透了其中的秘密了吗!!!

Dockerfile常用的指令

格式: INSTRUCTION argument (INSTRUCTION 不区分大小写,但是常用大写)

1.FROM
格式: FROM image or FORM image:tag
精解:FROM 是用于指定基础的 images,Dockerfile 均以 FROM 开头,FROM 命令指明 Dockerfile 所创建的镜像文件以什么镜像为基础,FROM 以后的所有指令都会在 FROM 的基础上进行创建镜像。同一个 Dockerfile 中可多次使用 FROM 命令用于创建多个镜像

2.MAINTAINER
格式:MAINTAINER name
精解:MAINTAINER 是用于指定镜像创建者和联系方式,这里设置成你的 ID 和邮箱即可

3.COPY
格式: COPY src dest
精解:COPY 是用于复制本地主机的 src (Dockerfile 所在目录的相对路径)到容器中的 dest ,当使用本地目录为源目录时,推荐使用 COPY

4.WORKDIR
格式:WORKDIR /path/to/work/dir
精解:WORKDIR 用于配合 RUN,CMD,ENTRYPOINT 命令设置当前工作路径。可以设置多次,如果是相对路径,则相对前一个 WORKDIR 命令。默认路径为/。

5.RUN
格式:RUN command
精解:RUN 用于容器内部执行命令。每个 RUN 命令相当于在原有的镜像基础上添加了一个改动层,原有的镜像不会有变化

6.EXPOSE
格式:EXPOSE port [port…]
精解:EXPOSE 命令用来指定对外开放的端口

7.ENTRYPOINT
格式一:ENTRYPOINT [“executable”, “param1”, “param2”] :推荐使用的 exec形式
格式二:ENTRYPOINT command param1 param2 :shell 形式
精解:ENTRYPOINT 可以让你的容器表现得像一个可执行程序一样。一个 Dockerfile 中只能有一个 ENTRYPOINT,如果有多个,则最后一个生效。

8.CMD
格式一:CMD [“executable”,”param1”,”param2”]:推荐使用的 exec 形式。
格式二:CMD [“param1”,”param2”]:无可执行程序形式
格式三:CMD command param1 param2:shell 形式
精解:CMD 命令用于启动容器时默认执行的命令,CMD 命令可以包含可执行文件,也可以不包含可执行文件。不包含可执行文件的情况下就要用 ENTRYPOINT 指定一个,然后 CMD 命令的参数就会作为ENTRYPOINT的参数,一个 Dockerfile 中只能有一个CMD,如果有多个,则最后一个生效。而 CMD 的 shell 形式默认调用 /bin/sh -c 执行命令。CMD 命令会被 Docker 命令行传入的参数覆盖:docker run busybox /bin/echo Hello Docker 会把 CMD 里的命令覆盖。

构建Dockerfile实例

该说的上面都已经说完了,那么下面我们就一起做一个实例小试一下牛刀吧

FROM nginx

MAINTAINER kang <1468140258@qq.com>

RUN echo '

Hello, DockerFile !

' > /usr/share/nginx/html/index.html

然后在Dockerfile 文件所在目录执行:

1、构建
docker build -t repo/nginx_demo:v1

-t 是为新镜像设置仓库和名称,
repo 为仓库名,
nginx_demo 为镜像名,
v1是标签

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

2、启动此容器

docker run –name nginx_demo -d -p 8080:80 repo/nginx_demo:v1

这样我们可以用浏览器去访问这个 nginx 服务器:http://localhost:8080/ ,此时页面将返回信息: Hello, DockerFile !

对此这个例子就结束了,是不是特别简单呐,自己也动手写一个吧

注:可能会遇到的问题:
问题:Error response from daemon: pull access denied for centos7, repository does not exist or may require ‘docker login’: denied: requested access to the resource is denied

解答:前往官网注册—https://hub.docker.com/ ,注册后在命令行登录即可–> docker login

问题:Error response from daemon: Get https://registry-1.docker.io/v2/library/centos/manifests/latest: Get https://auth.docker.io/token?account=huanhuanlove&scope=repository%3Alibrary%2Fcentos%3Apull&service=registry.docker.io: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

第一步:通过dig @114.114.114.114 registry-1.docker.io找到可用IP
第二步:尝试修改/etc/hosts强制docker.io相关的域名解析到其它可用IP,添加 54.164.230.151 registry-1.docker.io
第三步:保存重试


   转载规则


《Docker风流史》 kang 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录