虚拟化技术
什么是虚拟化
在计算机技术中,虚拟化(Virtualization)是一种资源管理技术。它是将计算机的各种实体资源,如:服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以用更好的方式来利用这些资源。
虚拟化的目的是为了在同一个主机上运行多个系统或应用,从而提高系统资源的利用率,并带来降低成本、方便管理和容错容灾等好处。
虚拟化技术分类
从实现形式来分,虚拟化技术可分为基于硬件的虚拟化和基于软件的虚拟化。
1、硬件虚拟化
**硬件虚拟化就是硬件物理平台本身提供了对特殊指令的截获和重定向的支持,支持虚拟化的硬件,也是一些基于硬件实现软件虚拟化技术的关键。**在基于硬件实现软件虚拟化的技术中,在硬件是实现虚拟化的基础,硬件(主要是CPU)会为虚拟化软件提供支持,从而实现硬件资源的虚拟化。
支持虚拟化的硬件有:
- Intel-VT-(Intel Virtualization Technology),Intel公司为解决纯软件虚拟化解决方案在可靠性、安全性和性能上的不足而引进的技术。它可以让一个CPU工作起来像多个CPU在并行运行,从而使得在一部电脑内同时运行多个操作系统成为可能
- AMD-V-(AMD Virtualization),是AMD公司的虚拟化技术。**它是对x86处理器系统架构的一组硬件扩展和硬件辅助虚拟化技术,**可以简化纯软件的虚拟化解决方案,改进VMM(虚拟机监视器)的设计,更充分地利用硬件资源,提高服务器和数据中心的虚拟化效率。
2、软件虚拟化
**软件虚拟化就是利用软件技术,在现有的物理平台上实现对物理平台访问的截获和模拟。**在软件虚拟化技术中,有些技术不需要硬件支持,如:QEMU;而有些软件虚拟化技术,则依赖硬件支持,如:VMware、KVM。
对软件虚拟化进行细分,又可以分为以下几类:
- 完全虚拟化:(Full Virtualization)虚拟机模拟完整的底层硬件环境和特权指令的执行过程,使客户机操作系统可以独立运行。支持完全虚拟化的软件有:Parallels Workstation、VirtualBox、Virtual Iron、Oracle VM、Virtual PC、Virtual Server、Hyper-V、VMware Workstation、QEMU等
- 硬件辅助虚拟化:(Hardware-assisted Virtualization)**是指通过硬件辅助支持模拟运行环境,使客户机操作系统可以独立运行,实现完全虚拟化的功能。**支持硬件辅助虚拟化的软件有:Linux KVM、VMware Workstation、VMware Fusion、Virtual PC、Xen、VirtualBox、Parallels Workstation等
- 部分虚拟化:(Partial Virtualization)**只针对部分硬件资源进行虚拟化,虚拟机模拟部分底层硬件环境,特别是地址空间。**这样的环境支持资源共享和线程独立,但是不允许建立独立的客户机操作系统。
- 平行虚拟化:(Para-Virtualization)虚拟机不需要模拟硬件,而是将部分硬件接口以软件的形式提供给客户机操作系统。如:早期的Xen。
- 操作系统层虚拟化:(OS-level virtualization)**这种技术将操作系统内核虚拟化,可以允许使用者空间软件实例被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运行。**这个软件实例,也被称为是一个容器(containers)、虚拟引擎(Virtualization engine)、虚拟专用服务器(virtual private servers)。每个容器的进程是独立的,对于使用者来说,就像是在使用自己的专用服务器。 Docker容器技术就是属于操作系统层虚拟化的范畴。
几种虚拟化技术
虚拟化是通过软件的方式模拟实体服务器,其初衷是为了解决“一种应用占用一台服务器”模式所带来的服务器数量剧增的问题,从而降低数据中心复杂度,简化管理难度。在虚拟化的发展过程中,出现过以下主要虚拟化技术或产品:
- Xen - 由剑桥大学开发的,一款开源的虚拟机监视器。采用ICA协议,它通过一种叫做准虚拟化的技术来获取高性能,甚至在一些与传统虚拟技术极度不友好的架构上(如:x86),Xen也有极佳的表现。Xen属于半虚拟化的技术,所以其性能损失非常小。Xen没有指令翻译,其或者使用使能理解和翻译虚拟操作系统发出的未修改指令的CPU(即:完全虚拟化);或者修改操作系统,使它发出的指令最优化,便于在虚拟化环境中执行(即:准虚拟化)。
- KVM - KVM是一个Linux kernel模块,可以使用modprobe来加载KVM,加载后还需要通过其他工具创建虚拟机。KVM是一个全虚拟化的解决方案,但需要CPU支持虚拟化功能。相比Xen来说,KVM可以更加方便的整合进Linux内核,但它还需要其它虚拟化软件(如:QEMU)才能实现虚拟化功能。
- LXC - 即:Linux Container,Linux容器,是一种轻量级的虚拟化的手段。它可以提供轻量级的虚拟化,以隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。容器会有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。
- OpenVZ - 是SWsoft公司开发的开源软件,是该公司Virtuozzo软件的基础产品,是基于Linux平台的操作系统级服务器虚拟化解决方案。通过OpenVZ,可以在单个物理服务器上创建多个相互隔离的虚拟专用服务器(VPS)并以最大的效率共享硬件和管理资源。其上运行虚拟服务器被称为VPS(Virtual Private Serve),每个VPS的运行环境和独立服务器完全一致。OpenVZ基于Linux系统内核及作业系统提供操作系统级虚拟化,在虚拟化过程中资源消耗非常小,官方宣称约1-2%。
- Hyper-V - 是微软件推出的一种虚拟化技术,可以采用半虚拟化或全虚拟的方式创建虚拟机。虽然它可以创建Windows或Linux操作系统,但其本身只能运行在Windows系统下,使用范围较为有限。
- Oracle VM - Oracle推出的服务器虚拟化软件,基于开源的Xen技术,包括Oracle VM Server和Oracle VM Manager两部分。
- VMWare - 是一家非常出名虚拟化软件公司,其产品涵盖服务器、桌面等各种虚拟化领域,如:VMware Workstation - 是一款桌面虚拟机软件,可以在一台实体机器上模拟完整的网络环境,并可运行多个Windows、DOS、Linux或Mac系统,是非常好的开发、测试、部署解决方案。从技术角度来说,VMware Workstation是一款完全虚拟化产品,可借助硬件辅助在不修改用户操作系统的情况下完整虚拟化操作系统。
- VMware ESX Server - 是一款适用于任何系统环境的企业级的虚拟机软件,可以认为是VMware Server的升级版。相比VMware Workstation来说,其功能更加强大,可以用于构建高伸缩和高可靠企业级服务器,并可实现远程管理、高级资源管理控制等高级功能。
Docker虚拟化
什么是容器?
容器就是将软件打包成标准化单元,以用于开发、交付和部署。
容器虚拟化的是操作系统而不是硬件,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。
什么是Docker?
**Docker是一个开源的应用容器引擎,它让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到安装了任何 Linux 发行版本的机器上。Docker基于LXC来实现类似VM的功能,可以在更有限的硬件资源上提供给用户更多的计算资源。**与同VM等虚拟化的方式不同,LXC不属于全虚拟化、部分虚拟化或半虚拟化中的任何一个分类,而是一个操作系统级虚拟化。
Docker是直接运行在宿主操作系统之上的一个容器,使用沙箱机制完全虚拟出一个完整的操作,容器之间不会有任何接口,从而让容器与宿主机之间、容器与容器之间隔离的更加彻底。每个容器会有自己的权限管理,独立的网络与存储栈,及自己的资源管理能,使同一台宿主机上可以友好的共存多个容器。
Docker借助Linux的内核特性,如:控制组(Control Group)、命名空间(Namespace)等,并直接调用操作系统的系统调用接口。从而降低每个容器的系统开销,并实现降低容器复杂度、启动快、资源占用小等特征。
为什么要用 Docker
- Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 “这段代码在我机器上没问题啊” 这类问题;——一致的运行环境
- 可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。——更快速的启动时间
- 避免公用的服务器,资源会容易受到其他用户的影响。——隔离性
- 善于处理集中爆发的服务器使用压力;——弹性伸缩,快速扩展
- 可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。——迁移方便
- 使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。——持续交付和部署
Docker和虚拟机的区别
虚拟机Virtual Machine与容器化技术(代表Docker)都是虚拟化技术,两者的区别在于虚拟化的程度不同。
区别
1、虚拟机
- 基础设施(Infrastructure)。它可以是你的个人电脑,数据中心的服务器,或者是云主机。
- 主操作系统(Host Operating System)。你的个人电脑之上,运行的可能是MacOS,Windows或者某个Linux发行版。
- 虚拟机管理系统(Hypervisor)。利用Hypervisor,可以在主操作系统之上运行多个不同的从操作系统。类型1的Hypervisor有支持MacOS的HyperKit,支持Windows的Hyper-V以及支持Linux的KVM。类型2的Hypervisor有VirtualBox和VMWare。
- 操作系统(Guest Operating System)。假设你需要运行3个相互隔离的应用,则需要使用Hypervisor启动3个从操作系统,也就是3个虚拟机。这些虚拟机都非常大,也许有700MB,这就意味着它们将占用2.1GB的磁盘空间。更糟糕的是,它们还会消耗很多CPU和内存。
- **各种依赖。**每一个从操作系统都需要安装许多依赖。如果你的的应用需要连接PostgreSQL的话,则需要安装libpq-dev;如果你使用Ruby的话,应该需要安装gems;如果使用其他编程语言,比如Python或者Node.js,都会需要安装对应的依赖库。
2、Docker容器
- 主操作系统(Host Operating System)。所有主流的Linux发行版都可以运行Docker。对于MacOS和Windows,也有一些办法"运行"Docker。
- Docker守护进程(Docker Daemon)。Docker守护进程取代了Hypervisor,它是运行在操作系统之上的后台进程,负责管理Docker容器。
- **各种依赖。**对于Docker,应用的所有依赖都打包在Docker镜像中,Docker容器是基于Docker镜像创建的。
- **应用。**应用的源代码与它的依赖都打包在Docker镜像中,不同的应用需要不同的Docker镜像。不同的应用运行在不同的Docker容器中,它们是相互隔离的。
虚拟技术对比
- 隔离性
在于隔离性上面,由于vm对操作系统也进行了虚拟化,隔离的更加彻底。而Docker共享宿主机的操作系统,隔离性较差。
- 运行效率
**由于vm的隔离操作,导致生成虚拟机的速率大大低于容器Docker生成的速度,因为Docker直接利用宿主机的系统内核。**比如openstack能够以10台/min的速度创建虚拟机,而docker可以做到在几秒钟之内创建大量容器,它们的启动速度是在数量级上的差距。
因为虚拟机增加了一层虚拟硬件层,运行在虚拟机上的应用程序在进行数值计算时是运行在Hypervisor虚拟的CPU上的;另外一方面是由于计算程序本身的特性导致的差异。虚拟机虚拟的cpu架构不同于实际cpu架构,数值计算程序一般针对特定的cpu架构有一定的优化措施,虚拟化使这些措施作废,甚至起到反效果。
- 资源利用率
在资源利用率上虚拟机由于隔离更彻底,因此利用率也会相对较低。
因为虚拟机增加了一层虚拟硬件层,运行在虚拟机上的应用程序在进行数值计算时是运行在Hypervisor虚拟的CPU上的;另外一方面是由于计算程序本身的特性导致的差异。虚拟机虚拟的cpu架构不同于实际cpu架构,数值计算程序一般针对特定的cpu架构有一定的优化措施,虚拟化使这些措施作废,甚至起到反效果。
小结
1、虚拟机是在物理资源层面实现的隔离,相对于虚拟机,Docker是APP层面实现的隔离,并且省去了虚拟机操作系统(Guest OS)),从而节省了一部分的系统资源;
2、Docker守护进程可以直接与主操作系统进行通信,为各个Docker容器分配资源;
3、可以将容器与主操作系统隔离,并将各个容器互相隔离。
4、虚拟机启动需要数分钟,而Docker容器可以在数毫秒内启动。
5、由于没有臃肿的从操作系统,Docker可以节省大量的磁盘空间以及其他系统资源。
虚拟机与容器docker的区别,在于vm多了一层guest OS,虚拟机的Hypervisor会对硬件资源也进行虚拟化,而容器Docker会直接使用宿主机的硬件资源。
两者的隔离级别:
- 服务器:比作一个大型的仓管基地,包含场地与零散的货物——相当于各种服务器资源。
- 虚拟机技术:比作仓库,拥有独立的空间堆放各种货物或集装箱,仓库之间完全独立——仓库相当于各种系统,独立的应用系统和操作系统。
- Docker:比作集装箱,操作各种货物的打包——将各种应用程序和他们所依赖的运行环境打包成标准的容器,容器之间隔离。
Docker 架构
Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。
- Docker 客户端(Client) : Docker 客户端通过命令行或者其他工具使用 Docker SDK (https://docs.docker.com/develop/sdk/) 与 Docker 的守护进程通信。
- Docker 主机(Host) :一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。
Docker 包括三个基本概念:
- 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
- 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
- 仓库(Repository):仓库可看着一个代码控制中心,用来保存镜像。
Docker镜像
当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载。
镜像列表
我们可以使用 docker images 来列出本地主机上的镜像
[root@pdai ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest ccc6e87d482b 4 weeks ago 64.2MB
hello-world latest fce289e99eb9 13 months ago 1.84kB
各个选项说明:
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签, 同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本
- IMAGE ID:镜像ID
- CREATED:镜像创建时间
- SIZE:镜像大小
查找镜像
以查找MySQL的镜像为例:
-
可以通过Docker Hub 进行查找
-
使用 docker search 命令来搜索镜像
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@pdai ~]# docker search mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL is a widely used, open-source relation… 9132 [OK]
mariadb MariaDB is a community-developed fork of MyS… 3233 [OK]
mysql/mysql-server Optimized MySQL Server Docker images. Create… 676 [OK]
centos/mysql-57-centos7 MySQL 5.7 SQL database server 68
mysql/mysql-cluster Experimental MySQL Cluster Docker images. Cr… 62
centurylink/mysql Image containing mysql. Optimized to be link… 61 [OK]
deitch/mysql-backup REPLACED! Please use http://hub.docker.com/r… 41 [OK]
bitnami/mysql Bitnami MySQL Docker Image 35 [OK]
tutum/mysql Base docker image to run a MySQL database se… 34
schickling/mysql-backup-s3 Backup MySQL to S3 (supports periodic backup… 29 [OK]
prom/mysqld-exporter 26 [OK]
linuxserver/mysql A Mysql container, brought to you by LinuxSe… 24
centos/mysql-56-centos7 MySQL 5.6 SQL database server 19
circleci/mysql MySQL is a widely used, open-source relation… 18
mysql/mysql-router MySQL Router provides transparent routing be… 14
arey/mysql-client Run a MySQL client from a docker container 13 [OK]
databack/mysql-backup Back up mysql databases to... anywhere! 10
openshift/mysql-55-centos7 DEPRECATED: A Centos7 based MySQL v5.5 image… 6
fradelg/mysql-cron-backup MySQL/MariaDB database backup using cron tas… 5 [OK]
genschsa/mysql-employees MySQL Employee Sample Database 4 [OK]
devilbox/mysql Retagged MySQL, MariaDB and PerconaDB offici… 2
ansibleplaybookbundle/mysql-apb An APB which deploys RHSCL MySQL 2 [OK]
jelastic/mysql An image of the MySQL database server mainta… 1
monasca/mysql-init A minimal decoupled init container for mysql 0
widdpim/mysql-client Dockerized MySQL Client (5.7) including Curl… 0 [OK]
- NAME: 镜像仓库源的名称
- DESCRIPTION: 镜像的描述
- OFFICIAL: 是否 docker 官方发布
- STARS: 类似 Github 里面的 star,表示点赞、喜欢的意思。
- AUTOMATED: 自动构建。
拉取镜像
现在拉取搜索出的MySQL
[root@pdai ~]# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
619014d83c02: Pull complete
9ced578c3a5f: Pull complete
731f6e13d8ea: Pull complete
3c183de42679: Pull complete
6de69b5c2f3c: Pull complete
00f0a4086406: Pull complete
84d93aea836d: Pull complete
f18efbfd8d76: Pull complete
012b302865d1: Pull complete
fe16fd240f59: Pull complete
ca3e793e545e: Pull complete
51d0f2cb2610: Pull complete
Digest: sha256:6d0741319b6a2ae22c384a97f4bbee411b01e75f6284af0cce339fee83d7e314
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
[root@pdai ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest 791b6e40940c 2 weeks ago 465MB
ubuntu latest ccc6e87d482b 4 weeks ago 64.2MB
hello-world latest fce289e99eb9 13 months ago 1.84kB
删除镜像
以hello-world为例
[root@pdai ~]# docker rmi hello-world
Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container c91b90b18884 is using its referenced image fce289e99eb9
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
发现报错了,这时候主要看两点:要么就是container实例存在,要么存在镜像依赖;
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a51d2f023c9 ubuntu:latest "/bin/sh -c 'while t…" 2 hours ago Exited (137) 2 hours ago gifted_brown
414bf796cbe4 ubuntu:latest "/bin/bash" 2 hours ago Exited (0) 2 hours ago pedantic_galileo
512061ebfa4c ubuntu:latest "/bin/bash" 2 hours ago Exited (0) 2 hours ago wizardly_brown
aa5e9ae5e5db ubuntu:latest "/bin/echo 'Hello wo…" 2 hours ago Exited (0) 2 hours ago affectionate_knuth
c91b90b18884 hello-world "/hello" 3 hours ago Exited (0) 3 hours ago admiring_pare
[root@pdai ~]# docker image inspect --format='{{.RepoTags}} {{.Id}} {{.Parent}}' $(docker image ls -q )
[mysql:latest] sha256:791b6e40940cd550af522eb4ffe995226798204504fe495743445b900e417a51
[ubuntu:latest] sha256:ccc6e87d482b79dd1645affd958479139486e47191dfe7a997c862d89cd8b4c0
[hello-world:latest] sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
显然,我们只要删除container即可:
[root@pdai ~]# docker rm c91b90b18884
c91b90b18884
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1a51d2f023c9 ubuntu:latest "/bin/sh -c 'while t…" 2 hours ago Exited (137) 2 hours ago gifted_brown
414bf796cbe4 ubuntu:latest "/bin/bash" 2 hours ago Exited (0) 2 hours ago pedantic_galileo
512061ebfa4c ubuntu:latest "/bin/bash" 2 hours ago Exited (0) 2 hours ago wizardly_brown
aa5e9ae5e5db ubuntu:latest "/bin/echo 'Hello wo…" 2 hours ago Exited (0) 2 hours ago affectionate_knuth
最后再来删除镜像吧
[root@pdai ~]# docker rmi hello-world
Untagged: hello-world:latest
Untagged: hello-world@sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
Deleted: sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3
更新镜像
针对上述ubuntu的镜像,可以在里面安装一些软件,然后重新生成一个镜像,这就是更新重新commit出一个新的镜像。例如:先跑一个ubuntu容器实例,同时在里面进行apt-get update
更新
[root@pdai ~]# docker run -it ubuntu:latest
root@0a1556ca3c27:/# apt-get update
Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
Get:4 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
Get:5 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [817 kB]
Get:6 http://archive.ubuntu.com/ubuntu bionic/main amd64 Packages [1344 kB]
Get:7 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [186 kB]
Get:8 http://archive.ubuntu.com/ubuntu bionic/restricted amd64 Packages [13.5 kB]
Get:9 http://archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [11.3 MB]
Get:10 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [27.5 kB]
Get:11 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [7064 B]
Get:12 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [818 kB]
Get:13 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 Packages [11.1 kB]
Get:14 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [1345 kB]
Get:15 http://archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [41.2 kB]
Get:16 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [1104 kB]
Get:17 http://archive.ubuntu.com/ubuntu bionic-backports/universe amd64 Packages [4252 B]
Get:18 http://archive.ubuntu.com/ubuntu bionic-backports/main amd64 Packages [2496 B]
Fetched 17.6 MB in 10s (1759 kB/s)
Reading package lists... Done
root@0a1556ca3c27:/# exit
exit
此时 ID 为 0a1556ca3c27 的容器,是按我们的需求更改的容器。我们可以通过命令 docker commit 来提交容器副本:
[root@pdai ~]# docker commit -m="update test" -a="pdai" 0a1556ca3c27 pdai/ubuntu:v1.0.1
sha256:b51e9f5f98cdb5b95c34181148ed7029f0150618aa8cd0e916b10b6aea1bd4c9
可以看到已经生成成功, 且镜像的大小不一样了:
[root@pdai ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pdai/ubuntu v1.0.1 b51e9f5f98cd 5 seconds ago 92.1MB
mysql latest 791b6e40940c 2 weeks ago 465MB
ubuntu latest ccc6e87d482b 4 weeks ago 64.2MB
生成镜像
生成镜像可以使用命令 docker build ,通过创建一个 Dockerfile 文件,其中包含一组指令来告诉 Docker 如何构建我们的镜像。
这里特意指定的Base镜像为上一步修改生成的pdai/ubuntu:v1.0.1
FROM pdai/ubuntu:v1.0.1
MAINTAINER pdai "pdai.tech"
RUN /bin/echo 'root:123456' |chpasswd
RUN useradd pdai
RUN /bin/echo 'pdai:123456' |chpasswd
RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
EXPOSE 22
EXPOSE 80
CMD /usr/sbin/sshd -D
稍微解释下:
- 每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。
- 第一条FROM,指定使用哪个镜像源
- RUN 指令告诉docker 在镜像内执行命令,安装了什么。。。
- 我们使用 Dockerfile 文件,通过 docker build 命令来构建一个镜像。
接下来生成镜像:
[root@pdai docker-test]# docker build -t pdai/ubuntu:v2.0.1 .
Sending build context to Docker daemon 2.048kB
Step 1/9 : FROM pdai/ubuntu:v1.0.1
---> b51e9f5f98cd
Step 2/9 : MAINTAINER pdai "pdai.tech"
---> Running in af026ee229ea
Removing intermediate container af026ee229ea
---> 0e961cb557c9
Step 3/9 : RUN /bin/echo 'root:123456' |chpasswd
---> Running in 96bd9c40c55e
Removing intermediate container 96bd9c40c55e
---> 9e8549720043
Step 4/9 : RUN useradd pdai
---> Running in 0117278f243c
Removing intermediate container 0117278f243c
---> 87c478df56da
Step 5/9 : RUN /bin/echo 'pdai:123456' |chpasswd
---> Running in e0381eabe71a
Removing intermediate container e0381eabe71a
---> 84fd07f978ae
Step 6/9 : RUN /bin/echo -e "LANG=\"en_US.UTF-8\"" >/etc/default/local
---> Running in 8d0052d9921f
Removing intermediate container 8d0052d9921f
---> 3ed0b248224c
Step 7/9 : EXPOSE 22
---> Running in 4b5d540567cd
Removing intermediate container 4b5d540567cd
---> c0a72ad140dd
Step 8/9 : EXPOSE 80
---> Running in c9620707d038
Removing intermediate container c9620707d038
---> df42b714ecc1
Step 9/9 : CMD /usr/sbin/sshd -D
---> Running in e178826b43fe
Removing intermediate container e178826b43fe
---> a733d5a264b5
Successfully built a733d5a264b5
Successfully tagged pdai/ubuntu:v2.0.1
参数说明:
-t
:指定要创建的目标镜像名.
:Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径
使用docker images 查看创建的镜像已经在列表中存在,镜像ID为a733d5a264b5
[root@pdai docker-test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pdai/ubuntu v2.0.1 a733d5a264b5 5 minutes ago 92.5MB
pdai/ubuntu v1.0.1 b51e9f5f98cd 15 hours ago 92.1MB
mysql latest 791b6e40940c 2 weeks ago 465MB
ubuntu latest ccc6e87d482b 4 weeks ago 64.2MB
我们可以使用新的镜像来创建容器
[root@pdai docker-test]# docker run -it pdai/ubuntu:v2.0.1 /bin/bash
root@f5332ebce695:/# id pdai
uid=1000(pdai) gid=1000(pdai) groups=1000(pdai)
root@f5332ebce695:/# exit
exit
从上面看到新镜像已经包含我们创建的用户 pdai。
镜像标签
可以使用 docker tag 命令,为镜像添加一个新的标签
[root@pdai ~]# docker tag a733d5a264b5 pdai/ubuntu:v3.0.1
[root@pdai ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pdai/ubuntu v2.0.1 a733d5a264b5 9 minutes ago 92.5MB
pdai/ubuntu v3.0.1 a733d5a264b5 9 minutes ago 92.5MB
pdai/ubuntu v1.0.1 b51e9f5f98cd 15 hours ago 92.1MB
mysql latest 791b6e40940c 2 weeks ago 465MB
ubuntu latest ccc6e87d482b 4 weeks ago 64.2MB
注意:
- docker tag 镜像ID,这里是 a733d5a264b5 ,用户名称、镜像源名(repository name)和新的标签名(tag)。
- 使用 docker images 命令可以看到,ID为a733d5a264b5的镜像多一个v3.0.1标签。
镜像导出和导入
- 镜像导出
[root@pdai ~]# docker images
dockREPOSITORY TAG IMAGE ID CREATED SIZE
pdai/ubuntu v2.0.2 57544a04cd1a 3 months ago 91.5MB
[root@pdai ~]# docker save > pdai-ubuntu-v2.0.2.tar 57544a04cd1a
[root@pdai ~]# ll | grep pdai-u
-rw-rw-r-- 1 root root 93898240 Jun 4 09:06 pdai-ubuntu-v2.0.2.tar
[root@pdai ~]#
- 镜像导入
docker load < pdai-ubuntu-v2.0.2.tar
其中-i
或者<
表示从文件输入。会成功导入镜像及相关元数据,包括tag信息
可以依据具体使用场景来选择命令
- 若是只想备份images,使用save、load即可
- 若是在启动容器后,容器内容有变化,需要备份,则使用export、import
Docker 容器
容器启动
[root@pdai docker-test]# docker run -it pdai/ubuntu:v2.0.1 /bin/bash
root@f5332ebce695:/# id pdai
uid=1000(pdai) gid=1000(pdai) groups=1000(pdai)
root@f5332ebce695:/# exit
exit
-it
可以连写的,表示-i -t
-t
: 在新容器内指定一个伪终端或终端。-i
: 允许你对容器内的标准输入 (STDIN) 进行交互
容器查看
-a
表示 all,所有的
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 20 minutes ago Exited (0) 20 minutes ago jolly_kepler
0a1556ca3c27 ubuntu:latest "/bin/bash" 16 hours ago Exited (0) 16 hours ago stoic_hodgkin
1a51d2f023c9 ubuntu:latest "/bin/sh -c 'while t…" 18 hours ago Exited (137) 18 hours ago gifted_brown
414bf796cbe4 ubuntu:latest "/bin/bash" 18 hours ago Exited (0) 18 hours ago pedantic_galileo
512061ebfa4c ubuntu:latest "/bin/bash" 18 hours ago Exited (0) 18 hours ago wizardly_brown
aa5e9ae5e5db ubuntu:latest "/bin/echo 'Hello wo…" 18 hours ago Exited (0) 18 hours ago affectionate_knuth
容器再启动
[root@pdai ~]# docker start f5332ebce695
f5332ebce695
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 32 minutes ago Up 4 seconds 22/tcp, 80/tcp jolly_kepler
容器停止和重启
[root@pdai ~]# docker stop f5332ebce695
f5332ebce695
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@pdai ~]# docker restart f5332ebce695
f5332ebce695
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 33 minutes ago Up 2 seconds 22/tcp, 80/tcp jolly_kepler
0a1556ca3c27 ubuntu:latest "/bin/bash" 16 hours ago Exited (0) 16 hours ago stoic_hodgkin
1a51d2f023c9 ubuntu:latest "/bin/sh -c 'while t…" 18 hours ago Exited (137) 18 hours ago gifted_brown
414bf796cbe4 ubuntu:latest "/bin/bash" 18 hours ago Exited (0) 18 hours ago pedantic_galileo
512061ebfa4c ubuntu:latest "/bin/bash" 18 hours ago Exited (0) 18 hours ago wizardly_brown
aa5e9ae5e5db ubuntu:latest "/bin/echo 'Hello wo…" 19 hours ago Exited (0) 19 hours ago affectionate_knuth
后台模式与进入
- 第一种:
docker attach
exit之后容器也停止了
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 38 minutes ago Up 2 seconds 22/tcp, 80/tcp jolly_kepler
[root@pdai ~]# docker attach f5332ebce695
root@f5332ebce695:/# echo 'pdai'
pdai
root@f5332ebce695:/# exit
exit
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- 第二种:
docker exec
[root@pdai ~]# docker exec -it f5332ebce695 /bin/bash
Error response from daemon: Container f5332ebce69520fba353f035ccddd4bd42055fbd1e595f916ba7233e26476464 is not running
[root@pdai ~]# docker restart f5332ebce695
f5332ebce695
[root@pdai ~]# docker exec -it f5332ebce695 /bin/bash
root@f5332ebce695:/# exit
exit
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 42 minutes ago Up 8 seconds 22/tcp, 80/tcp jolly_kepler
注意:
- 在容器停止状态下执行了
docker exec
,是让你看到docker exec
是在容器启动状态下用的,且注意下错误信息; - 推荐大家使用
docker exec
命令,因为此退出容器终端,不会导致容器的停止。
容器导出和导入
在生产环境中,很多时候是无法连接外网的,所以有时候需要用到容器的导入和导出。
- 容器的导出
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" 42 minutes ago Up 8 seconds 22/tcp, 80/tcp jolly_kepler
[root@pdai ~]# docker export f5332ebce695 > ubuntu-pdai-v2.tar
[root@pdai ~]# ll
-rw-rw-r-- 1 root root 93891072 Feb 18 09:42 ubuntu-pdai-v2.tar
同时你可以发现,导出容器的时候,容器无需关闭。
- 容器导入
[root@pdai ~]# docker import ubuntu-pdai-v2.tar pdai/ubuntu:v2.0.2
sha256:57544a04cd1ad330371ca9142184ff031dc2b6df70df177994477c08fe547b25
[root@pdai ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
pdai/ubuntu v2.0.2 57544a04cd1a 7 seconds ago 91.5MB
pdai/ubuntu v2.0.1 a733d5a264b5 About an hour ago 92.5MB
pdai/ubuntu v3.0.1 a733d5a264b5 About an hour ago 92.5MB
pdai/ubuntu v1.0.1 b51e9f5f98cd 16 hours ago 92.1MB
mysql latest 791b6e40940c 2 weeks ago 465MB
ubuntu latest ccc6e87d482b 4 weeks ago 64.2MB
注意看,SIZE可能是不一样的。
强制停止容器
使用docker rm -f 强制停止容器
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f5332ebce695 pdai/ubuntu:v2.0.1 "/bin/bash" About an hour ago Up 24 minutes 22/tcp, 80/tcp jolly_kepler
[root@pdai ~]# docker rm -f f5332ebce695
f5332ebce695
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0a1556ca3c27 ubuntu:latest "/bin/bash" 17 hours ago Exited (0) 17 hours ago stoic_hodgkin
1a51d2f023c9 ubuntu:latest "/bin/sh -c 'while t…" 19 hours ago Exited (137) 19 hours ago gifted_brown
414bf796cbe4 ubuntu:latest "/bin/bash" 19 hours ago Exited (0) 19 hours ago pedantic_galileo
512061ebfa4c ubuntu:latest "/bin/bash" 19 hours ago Exited (0) 19 hours ago wizardly_brown
aa5e9ae5e5db ubuntu:latest "/bin/echo 'Hello wo…" 19 hours ago Exited (0) 19 hours ago affectionate_knuth
清理停止的容器
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0a1556ca3c27 ubuntu:latest "/bin/bash" 17 hours ago Exited (0) 17 hours ago stoic_hodgkin
1a51d2f023c9 ubuntu:latest "/bin/sh -c 'while t…" 19 hours ago Exited (137) 19 hours ago gifted_brown
414bf796cbe4 ubuntu:latest "/bin/bash" 19 hours ago Exited (0) 19 hours ago pedantic_galileo
512061ebfa4c ubuntu:latest "/bin/bash" 19 hours ago Exited (0) 19 hours ago wizardly_brown
aa5e9ae5e5db ubuntu:latest "/bin/echo 'Hello wo…" 19 hours ago Exited (0) 19 hours ago affectionate_knuth
清理停止的容器: docker container prune
[root@pdai ~]# docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
0a1556ca3c275cc692ecd6d19caed4c5be42578f81b3dfea52b24208790d160a
1a51d2f023c947f2be2d9a78eb863e854ca302c89bf354654c409e23e7dd25d7
414bf796cbe403e01b5414f2b6232c6a037af78deee4581f4935c94859b5164e
512061ebfa4c340eb03833e54d77052e33fb62cd42ab7dd7e09bf0b02a761552
aa5e9ae5e5db1760bdb8c7ddb92e4293cd7b4736be7e97314f3ef44a71bf8930
Total reclaimed space: 27.93MB
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
容器别名及操作
docker run -itd --name
[root@pdai ~]# docker run -itd --name pdai-ubuntu-202 pdai/ubuntu:v2.0.2 /bin/bash
11de9755a08402d963d263a559a7daf48f4a2188398f258641240b5eb50fbc89
[root@pdai ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11de9755a084 pdai/ubuntu:v2.0.2 "/bin/bash" 5 seconds ago Up 4 seconds pdai-ubuntu-202
[root@pdai ~]# docker stop pdai-ubuntu-202
pdai-ubuntu-202
[root@pdai ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11de9755a084 pdai/ubuntu:v2.0.2 "/bin/bash" 26 seconds ago Exited (0) 4 seconds ago pdai-ubuntu-202
容器错误日志
例:实时查看docker容器名为user-uat的最后10行日志
docker logs -f -t --tail 10 user-uat
例:查看指定时间后的日志,只显示最后100行:
docker logs -f -t --since="2018-02-08" --tail=100 user-uat
例:查看最近30分钟的日志:
docker logs --since 30m user-uat
例:查看某时间之后的日志:
docker logs -t --since="2018-02-08T13:23:37" user-uat
例:查看某时间段日志:
docker logs -t --since="2018-02-08T13:23:37" --until "2018-02-09T12:23:37" user-uat
例:将错误日志写入文件:
docker logs -f -t --since="2018-02-18" user-uat | grep error >> logs_error.txt
Docker 仓库
仓库(Repository)是集中存放镜像的地方,它和我们的Maven仓库是一样的。当然不止 docker hub,只是远程的服务商不一样,操作都是一样的。
- 可以采用共有的仓库,也可以自己搭建Docker Registry;
- 如果之前有自己的Artifactory或者Nexus,它们同样可以支持Docker Registry功能;
- 带界面的也可以使用Harbor等;