引入
在生活中经常听到 Docker 这个词,但 Docker 到底是什么呐?此问题一出,致使很多人感到疑惑,Docker 不就是一个容器吗?类似的还有Tomcat、Jetty等,对此回答到底对不对呐,就请朋友们一起跟着我的脚步共同进入Docker的世界,一起来揭开 Docker 的庐山真面,看看 Docker 背后到底藏着什么 Secret(秘密)。
Docker是何物?
官方解读:
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。其口号–“一次创建,到处运行”。
个人经验总结:
- docker是一个开源的软件部署解决方案;
- docker也是轻量级的应用容器框架;
- docker可以打包、发布、运行任何的应用
Dcoker为何而生?
Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源。
1.看一下不使用Docker的开发部署几条缺点:
- 资源利用率相对较低
- 但物理机多应用无法有效隔离(如CPU、进程、磁盘)
- 测试、版本管理复杂
- 迁移成本高且较为麻烦
- 传统虚拟机空间占用大、启动慢、管理复杂
- 开发人员可以消除协作编码时“在我的机器上可正常工作”的问题。
- 运维人员可以在隔离容器中并行运行和管理应用,获得更好的计算密度。
从上面不使用Docker开发部署的几条缺点可以看出Docker到底为何而生了吧,且也正好引出了Docker的优点所在。“鱼和熊掌不可得兼”这个道理大家应该都懂吧,所以说有长必有短,既然Docker有这么多的好处,那也必然有其局限之处。
井底之Docker
- Docker是基于Linux 64bit的,无法在32bit的linux/Windows/unix环境下使用
- LXC是基于cgroup等linux kernel功能的,因此container的guest系统只能是linux base的
- 隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库
- 网络管理相对简单,主要是基于namespace隔离
- cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是按内存收费)
- Docker对disk的管理比较有限
- 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 使用了 C/S 结构,即客户端/服务器体系结构。 Docker 客户端与 Docker 服务器进行交互,Docker服务端负责构建、运行和分发 Docker 镜像。 Docker 客户端和服务端可以运行在一台机器上,可以通过 RESTful、Socket 或网络接口与远程 Docker 服务端进行通信。
通过上图大致我们可以了解到,Docker 的核心组件包括:
- Docker Client
- Docker daemon
- Docker Image
- Docker Registry
- 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 上,负责创建、运行、监控容器,构建、存储镜像。
运行过程的作用有以下几种可能:
- 向 Docker Registry 获取镜像
- 通过 graphdriver 执行容器镜像的本地化操作
- 通过 networkdriver 执行容器网络环境的配置
- 通过 execdriver 执行容器内部运行的执行工作
- 由于 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
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 启动容器
一起来看一下具体流程吧
运行容器
查看镜像
查看正在运行的容器
上面步骤就是Docker运行一个容器的步骤,知道了这些再使用Docker命令是思路是不是清晰了许多。
Docker常用命令温故
DockerFile是何物
上面我们已经提到过DockerFile了,但它到底是何方神圣呐,带着疑问跟着我的步伐一起进入DockerFile的世界看看吧。
Dockerfile 是自动构建 docker 镜像的配置文件, 用户可以使用 Dockerfile 快速创建自定义的镜像。Dockerfile 中的命令非常类似于 linux 下的 shell 命令。且Dockerfile 可以自定义镜像,通过 Docker 命令去运行镜像,从而达到启动容器的目的。
我们可以通过下面这幅图来直观地感受下 Docker 镜像、容器和 Dockerfile 三者之间的关系。
Dockerfile 是由一行行命令语句组成,且支持已 # 开头的注释行。
一般可以将 Dockerfile 分为四个部分:
- 基础镜像(父镜像)信息指令 FROM
- 维护者信息指令 MAINTAINER
- 镜像操作指令 RUN 、 EVN 、 ADD 和 WORKDIR 等
- 容器启动指令 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"]
我们可以分析一下上面这个过程:
- 从 Docker Hub 上 pull 下 python 2.7 的基础镜像
- 显示维护者的信息
- copy 当前目录到容器中的 /app 目录下 复制本地主机的
( Dockerfile 所在目录的相对路径)到容器里 - 指定工作路径为 /app
- 安装依赖包
- 暴露 5000 端口
- 启动 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
第三步:保存重试