Docker

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。

虚拟机与容器的区别

容器虚拟化的是操作系统而不是硬件,容器之间共享的是一套操作系统的资源。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。

Docker 容器的特点

轻量
在一台机器上运行的多个 Docker 容器可以共享这台机器的操作系统内核;它们能够迅速启动,只需占用很少的计算和内存资源。镜像是通过文件系统层进行构造的,并共享一些公共文件。这样就能尽量降低磁盘用量,并能更快地下载镜像。

标准
Docker 容器基于开放式标准,能够在所有主流 Linux 版本、Microsoft Windows 以及包括 VM、裸机服务器和云在内的任何基础设施上运行。

安全
Docker 赋予应用的隔离性不仅限于彼此隔离,还独立于底层的基础设施。Docker 默认提供最强的隔离,因此应用出现问题,也只是单个容器的问题,而不会波及到整台机器。


为什么要用 Docker ?

Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码在我机器上没问题啊” 这类问题;——一致的运行环境
可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。——更快速的启动时间
避免公用的服务器,资源会容易受到其他用户的影响。——隔离性
善于处理集中爆发的服务器使用压力;——弹性伸缩,快速扩展
可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。——迁移方便
使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。——持续交付和部署


Docker的应用场景

Web 应用的自动化打包和发布。

自动化测试和持续集成、发布。

在服务型环境中部署和调整数据库或其他的后台应用。

从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。


Docker 架构

Docker 包括三个基本概念:

镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。

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

容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。所以,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。

仓库(Repository):仓库可看着一个代码控制中心,用来保存镜像。

镜像构建完成后,可以很容易的在当前宿主上运行,但是, 如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。所以说:镜像仓库是 Docker 用来集中存放镜像文件的地方类似于我们之前常用的代码仓库。

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

最常使用的 Registry 公开服务是官方的 Docker Hub ,这也是默认的 Registry,并拥有大量的高质量的官方镜像

我们可以通过 docker search 这个命令搜索 Docker Hub 中的镜像,搜索的结果是一致的。

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。

Docker 容器通过 Docker 镜像来创建。

容器与镜像的关系类似于面向对象编程中的对象与类。

原来这就是Docker


Docker安装

不同操作系统的Docker安装步骤不一样,需要根据自己的操作系统来进行相应的安装

以下是CentOS的Docker安装

安装 Docker Engine-Community
使用 Docker 仓库进行安装
在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库。之后,您可以从仓库安装和更新 Docker。

设置仓库

安装所需的软件包。yum-utils 提供了 yum-config-manager ,并且 device mapper 存储驱动程序需要 device-mapper-persistent-data 和 lvm2。

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

使用以下命令来设置稳定的仓库。

sudo yum-config-manager
–add-repo
https://download.docker.com/linux/centos/docker-ce.repo

安装 Docker Engine-Community
安装最新版本的 Docker Engine-Community 和 containerd

sudo yum install docker-ce docker-ce-cli containerd.io

containerd 是什么?

docker 对容器的管理和操作基本都是通过 containerd 完成的。
1、那么,containerd 是什么呢?
Containerd 是一个工业级标准的容器运行时,它强调简单性、健壮性和可移植性。
Containerd 可以在宿主机中管理完整的容器生命周期:

容器镜像的传输和存储、
容器的执行和管理、
存储和网络等。
详细点说,Containerd 负责干下面这些事情:

管理容器的生命周期(从创建容器到销毁容器)
拉取/推送容器镜像
存储管理(管理镜像及容器数据的存储)
调用 runC 运行容器(与 runC 等容器运行时交互)
管理容器网络接口及网络
注意:Containerd 被设计成嵌入到一个更大的系统中,而不是直接由开发人员或终端用户使用。

2、为什么需要containerd
我们可以从下面几点来理解为什么需要独立的 containerd:

继续从整体 docker 引擎中分离出的项目(开源项目的思路)
可以被 Kubernets CRI 等项目使用(通用化)
为广泛的行业合作打下基础(就像 runC 一样)

如果我们要安装特定版本的Docker CE,可以在存储库中列出可用版本,然后选择并安装:

提示:Docker CE有三个更新频道,分别为stable、test、nightly,stable是稳定版本,test是测试后的预发布版本,而nightly则是开发中准备在下一个版本正式发布的版本,我们可以根据自己的需求下载安装。

1、列出并排序您存储库中可用的版本。

yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable

2、通过其完整的软件包名称安装特定版本,该软件包名称是软件包名称(docker-ce)加上版本字符串(第二列),从第一个冒号(:)一直到第一个连字符,并用连字符(-)分隔。例如:docker-ce-18.09.1。

sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io

安装完成之后,我们可以使用以下命令来看Docker是否安装成功
docker version #如果显示了docker的版本信息,说明安装成功

启动 Docker
如果我们想让Docker开机自行启动,可以使用以下命令,这样我们关机或者重启后就不需要手动启动Docker
sudo systemctl enable docker

安装完Docker后,我们使用以下命令启动Docker

sudo systemctl start docker

hello-world

运行了docker之后,我们来进行hello-world入门

docker: Docker 的二进制执行文件。

run: 与前面的 docker 组合来运行一个容器。

#拉取hello-world镜像
docker pull hello-world

#运行一个容器
docker run hello-world


Docker的基本使用和指令

接下来,介绍一些docker的基本使用和指令

容器:

获取镜像
如果我们本地没有 ubuntu 镜像,我们可以使用 docker pull 命令来载入 ubuntu 镜像:

docker pull ubuntu

启动容器
以下命令使用 ubuntu 镜像启动一个容器,参数为以命令行模式进入该容器:

docker run -it ubuntu /bin/bash

参数说明:

-i: 交互式操作。
-t: 终端。
ubuntu: ubuntu 镜像。
/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
要退出终端,直接输入 exit:

docker run imageName:创建一个新的容器并运行一个命令

docker run -d imageName:后台运行容器,并返回容器ID;

docker ps :查看运行的容器

输出详情介绍:

CONTAINER ID: 容器 ID。

IMAGE: 使用的镜像。

COMMAND: 启动容器时运行的命令。

CREATED: 容器的创建时间。

STATUS: 容器状态。

状态有7种:

created(已创建)
restarting(重启中)
running(运行中)
removing(迁移中)
paused(暂停)
exited(停止)
dead(死亡)
PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。

NAMES: 自动分配的容器名称。

docker logs Name:获取容器的日志

例:docker logs -f nginx

docker stop Name:停止运行中的容器

例:docker stop nginx

后台运行容器之后,想要进入容器,可以通过以下指令进入:

docker exec 容器ID

镜像

docker images :列出本地主机上的所有镜像

REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 14.04 90d5884b1ee0 5 days ago 188 MB
php 5.6 f40e9e0f10c8 9 days ago 444.8 MB
nginx latest 6f8d099c3adc 12 days ago 182.7 MB
mysql 5.6 f2e8d6c772c0 3 weeks ago 324.6 MB
httpd latest 02ef73cf1bc0 3 weeks ago 194.4 MB
ubuntu 15.10 4e3b13c8a266 4 weeks ago 136.3 MB
hello-world latest 690ed74de00f 6 months ago 960 B
training/webapp latest 6fae60ef3446 11 months ago 348.8 MB

各个选项说明:

REPOSITORY:表示镜像的仓库源

TAG:镜像的标签

IMAGE ID:镜像ID

CREATED:镜像创建时间

SIZE:镜像大小

同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本,如 ubuntu 仓库源里,有 15.10、14.04 等多个不同的版本,我们使用 REPOSITORY:TAG 来定义不同的镜像。

所以,我们如果要使用版本为15.10的ubuntu系统镜像来运行容器时,命令如下:

[email protected]:~$ docker run -t -i ubuntu:15.10 /bin/bash

docker search:查找镜像

docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 3260 [OK]

NAME: 镜像仓库源的名称

DESCRIPTION: 镜像的描述

OFFICIAL: 是否 docker 官方发布

AUTOMATED: 自动构建。

docker pull :拉取镜像

docker rmi:删除镜像
例:docker rmi nginx

创建镜像
当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。

1、从已经创建的容器中更新镜像,并且提交这个镜像
2、使用 Dockerfile 指令来创建一个新的镜像

更新镜像
更新镜像之前,我们需要使用镜像来创建一个容器。
[email protected]:~$ docker run -t -i ubuntu:15.10 /bin/bash
[email protected]:/#
在运行的容器内使用 apt-get update 命令进行更新。

在完成操作之后,输入 exit 命令来退出这个容器。

此时 ID 为 e218edb10161 的容器,是按我们的需求更改的容器。我们可以通过命令 docker commit 来提交容器副本。

[email protected]:~$ docker commit -m=“has update” -a=“runoob” e218edb10161 runoob/ubuntu:v2
sha256:70bf1840fd7c0d2d8ef0a42a817eb29f854c1af8f7c59fc03ac7bdee9545aff8
各个参数说明:

-m: 提交的描述信息

-a: 指定镜像作者

e218edb10161:容器 ID

runoob/ubuntu:v2: 指定要创建的目标镜像名

然后就可以使用我们更新的镜像来创建容器了

docker run -t -i runoob/ubuntu:v2 /bin/bash

构建镜像
我们使用命令 docker build , 从零开始来创建一个新的镜像。为此,我们需要创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像。
cat Dockerfile

然后,我们使用 Dockerfile 文件,通过 docker build 命令来构建一个镜像。
docker build -t runoob/centos:7 .

参数说明:

-t :指定要创建的目标镜像名

. :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径

设置镜像标签
我们可以使用 docker tag 命令,为镜像添加一个新的标签。

docker tag 860c279d2fec runoob/centos:dev

docker tag 镜像ID,这里是 860c279d2fec ,用户名称、镜像源名(repository name)和新的标签名(tag)。

网络端口映射
我们创建了一个 python 应用的容器。

[email protected]:~$ docker run -d -P training/webapp python app.py
fce072cc88cee71b1cdceb57c2821d054a4a59f67da6b416fceb5593f059fc6d
另外,我们可以指定容器绑定的网络地址,比如绑定 127.0.0.1。

我们使用 -P 参数创建一个容器,使用 docker ps 可以看到容器端口 5000 绑定主机端口 32768。

[email protected]:~$ docker ps
CONTAINER ID IMAGE COMMAND … PORTS NAMES
fce072cc88ce training/webapp “python app.py” … 0.0.0.0:32768->5000/tcp grave_hopper
我们也可以使用 -p 标识来指定容器端口绑定到主机端口。

两种方式的区别是:

-P :是容器内部端口随机映射到主机的高端口。
-p : 是容器内部端口绑定到指定的主机端口。
[email protected]:~$ docker run -d -p 5000:5000 training/webapp python app.py
33e4523d30aaf0258915c368e66e03b49535de0ef20317d3f639d40222ba6bc0
[email protected]:~$ docker ps
CONTAINER ID IMAGE COMMAND … PORTS NAMES
33e4523d30aa training/webapp “python app.py” … 0.0.0.0:5000->5000/tcp berserk_bartik
fce072cc88ce training/webapp “python app.py” … 0.0.0.0:32768->5000/tcp grave_hopper
另外,我们可以指定容器绑定的网络地址,比如绑定 127.0.0.1。

[email protected]:~$ docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py

这样我们就可以通过访问 127.0.0.1:5001 来访问容器的 5000 端口。

相关文章: