Docker初级使用指南

目录

  1. 什么是Docker
    1. Docker开源项目
    2. Linux容器技术
    3. 从Linux容器到Docker
  2. 为什么要使用Docker
    1. Docker容器虚拟化的好处
    2. Docker在开发和运维中的优势
    3. Docker与虚拟机比较
    4. 虚拟化与Docker
  3. 核心概念
    1. Docker镜像
    2. Docker容器
    3. Docker仓库
    4. 安装Docker
  4. Docker镜像
    1. 获取镜像
    2. 查看镜像信息
    3. 搜寻镜像
    4. 删除镜像
    5. 创建镜像
      1. 基于已有镜像的容器创建
      2. 基于本地模板导入
      3. 基于Dockerfile创建
    6. 存储和载入镜像
      1. 存储镜像
      2. 载入镜像
      3. 上传镜像
  5. Docker容器
    1. 创建容器
      1. 新建容器
      2. 新建并启动容器
      3. 守护态运行
    2. 终止容器
    3. 进入容器
      1. attach命令
      2. exec命令
      3. nsenter工具
    4. 删除容器
    5. 导入和导出容器
      1. 导出容器
      2. 导入容器
  6. Docker仓库
    1. Docker Hub
    2. 创建和使用私有仓库
      1. 使用registry镜像创建私有仓库
      2. 管理私有仓库镜像
        1. 出现错误

什么是Docker

Docker开源项目

Docker是基于Go语言实现的云开源项目,诞生于2013年初,最初的发起者是dotCloud公司。dotCloud公司后来改名为Docker Inc,专注于Docker相关技术和产品的开发。
Docker的主要目标是“Build, Ship and Run Any App, Anywhere”,即通过对应用组件的封装(Packaging)、分发(Distribution)、部署(Deployment)、运行(Runtime)等设备能生命周期的管理,达到应用组件级别的“一次封装,到处运行”。这里的应用组件,既可以是一个web应用,也可以是一套数据库服务,甚至是一个操作系统或编译器。

Docker基于Linux的多项开源技术提供了高效、敏捷和轻量级的容器方案,并且支持在多种主流云平台(PaaS)和本地系统上部署。可以说Docker为应用的开发和部署提供了“一站式”的解决方案。

Linux容器技术

Docker 引擎的基础是Linux容器(Linux Containers,LXC)技术。

容器有效的将由单个操作系统管理的资源划分到孤立的组中,以便更好地在孤立的组中之间平衡有冲突的资源使用需求。与虚拟化相比,这样既不需要指令级模拟,也不需要及时编译。容器可以在核心CPU本地运行指令,而不需要任何专门的解释机制。此外也避免了准虚拟化(paravirtualization)和系统调用替换中的复杂性。

LXC被集成到了主流Linux内核中,进而成为Linux系统轻量级容器技术的事实标准。

从Linux容器到Docker

在LXC的基础上,Docker进一步优化了容器的使用体验。Docker提供了各种容器管理工具(如分发、版本、移植等)让用户无需关注底层的操作,可以简单明了地管理和使用容器。用户操作Docker容器就像操作一个轻量级的虚拟机那样简单。
可以简单地将Docker容器理解为一种沙盒(SandBox),每个容器内运行一个应用,不同的容器相互隔离,容器之间也可以建立通信机制。容器的创建和停止都十分快速,容器自身对资源的需求也十分有限,远低于虚拟机。

为什么要使用Docker

Docker容器虚拟化的好处

高效地构建应用。Docker通过容器打包应用,节约时间,降低部署过程出现问题的风险。

Docker在开发和运维中的优势

  • 更快速的交付和部署。使用Docker,开发人员可以使用镜像来快速构建一套标准的开发环境;开发完成后,测试和运维人员可以直接使用相同环境来部署代码。Docker可以快速创建和删除容器,实现快速迭代,大量节约开发、测试、部署的时间。并且,各个步骤都有明确的配置和操作,整个过程全程可见,使团队更容易理解应用的创建和工作过程。
  • 更高效的资源利用。Docker容器的运行不需要额外的虚拟化管理程序(Virtual Machine Manager,VMM,以及Hypervisor)支持,它是内核级的虚拟化,可以实现更高的性能,同时对资源的额外要求很低。
  • 更轻松的迁移和扩展。Docker容器几乎可以在任意平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等。这种兼容性让用户可以在不同平台之间轻松地迁移应用。
  • 更简单的更新管理。使用Dockerfile,只需要小小的配置修改,就可以代替以往大量的更新工作。并且所有的修改都以增量的方式进行分发和更新,从而实现自动化并且高效的容器管理。

Docker与虚拟机比较

Docker在运行应用上相比传统虚拟机方式具有显著的优势:

  • Docker容器很快,启动和停止可以在秒级实现。
  • Docker容器对系统资源需求很少,一台主机可以同时运行数千个Docker容器。
  • Docker通过类似Git的操作来方便用户获取、分发和更新应用镜像,指令简明,学习成本低。
  • Docker通过Dockerfile配置文件来支持灵活的自动化创建和部署机制,提高工作效率。
特性 容器 虚拟机
启动速度 秒级 分钟级
硬盘使用 一般为MB 一般为GB
性能 接近原生 弱于
系统支持量 单机支持上千个容器 一般几十个
隔离性 安全隔离 完全隔离

虚拟化与Docker

虚拟化技术,在计算机领域,一般指的是计算机虚拟化(Computing Virtualization),或通常说的服务器虚拟化。

在计算机技术中,虚拟化(Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存级存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以用比原来的组态更好的方式来应用这些资源。

虚拟化的核心就是对资源进行抽象,目标往往是为了同一个主机上运行多个系统或应用,从而提高系统资源的利用率,同时降低成本,方便管理和容错容灾等好处。

从大类上分,虚拟化技术可以分为基于硬件的虚拟化和基于软件的虚拟化。其中,真正意义上的基于硬件的虚拟化技术不多见,少数如网卡中的单根多IO虚拟化(Single Root I/O Virtualization and Sharing Specificatio,SR-IOV)等技术。

基于软件的虚拟化从对象所在的层次,又可以分为应用虚拟化和平台虚拟化(通常说的虚拟化技术即属于这个范畴)。其中,前者一般指的一些模拟设备或Wine这样的软件。后者又可以详细分为:

Virtualization* 完全虚拟化。虚拟机模拟完整的底层硬件环境和特权指令的执行过程,客户机操作系统无需进行修改。例如VMware Workstation、VirtualBox、QEMU等。

  • 硬件辅助虚拟化。利用硬件(主要是CPU)辅助支持(目前x86体系结构上可用的硬件辅助虚拟化技术包括Intel-VT和AMD-V)处理敏感指令来实现完全虚拟化的功能,客户机操作系统无需修改,例如VMware WorkStation、Xen、KVM。
  • 部分虚拟化。只针对部分硬件资源进行虚拟化,客户端操作系统需要进行修改。现在有些虚拟化技术的早期版本仅支持部分虚拟化。
  • 超虚拟化(paravirtualization)。部分硬件接口以软件的形式提供给客户机操作系统,客户机操作系统需要进行修改,例如早期的Xen。
  • 操作系统级虚拟化。内核通过创建多个虚拟的操作系统(内核和库)来隔离不同的进程。容器相关技术即在这个范畴。

Docker和常见的虚拟机方式的不同之处。
传统方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统层。
Docker容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,因而更加轻量级。

Docker和传统的虚拟机方式的不同之处Docker和传统的虚拟机方式的不同之处

核心概念

Docker镜像

Docker镜像(Image)类似于虚拟机镜像,可以将它理解为一个面向Docker引起的只读模板,包含了文件系统。
镜像是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像,用户甚至可以从网上下载一个已经做好的应用镜像,并通过简单的命令就可以直接使用。

Docker容器

Docker容器(Container)类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。
容器是从镜像创建的应用运行实例,可以将其启动、开始、停止、删除,而这些容器都是相互隔离、互不可见的。
镜像自身是只读的。容器从镜像启动的时候,Docker会在镜像的最上层创建一个可写层,镜像本身将保持不变。

Docker仓库

Docker仓库(Repository)类似于代码仓库,是Docker集中存放镜像文件的场所。
Docker注册服务器(Registry)是存放仓库的地方。每个仓库中存放某一类镜像,往往包括多个镜像文件,通过不同的标签(tag)来进行区分。

根据所存储的镜像公开分享与否,Docker仓库可分为公开的仓库(Public)和私有仓库(Private)两种形式。

用户不希望公开分享自己的镜像文件,Docker支持用户在本地网络内创建一个只能自己访问的私有仓库。

当用户创建了自己的镜像后,就可以使用push命令将它上传到指定的仓库中。这样下一次用户在另外一台机器上使用该镜像时,只需将其从仓库上pull下来就可以了。

安装Docker

安装

Docker镜像

镜像是Docker的三大核心概念之一。
Docker运行容器前需要本地存在对应的镜像,如果不存在本地,Docker会尝试先从默认镜像仓库下载(Docker Hub),用户也可以通过配置,使用自定义的镜像仓库。

获取镜像

命令的格式。

1
docker pull NAME[:TAG]

从Docker Hub的Ubuntu仓库下载最新的Ubuntu操作系统的镜像。

1
sudo docker pull ubuntu
下载Ubuntu镜像下载Ubuntu镜像

下载过程中,镜像文件一般由若干层组成,行首的afde35469481字符串代表了各层的ID。

层(Layer)其实是AUFS(Advanced Union File System,一种联合文件系统)中的重要概念,是实现增量保存于更新的基础。

指定标签下载指定版本的镜像

1
sudo docker pull ubuntu:16.04

查看镜像信息

使用docker images命令可以查看本地主机上已有的镜像。

1
sudo docker images
查看镜像查看镜像

pepository 来自哪个仓库
tag 镜像的标签信息
image id 镜像的id(唯一)
created 创建时间
virtual size 镜像大小

使用docker inspect获取镜像的详细信息

1
sudo docker inspect [image id]
查看镜像详细查看镜像详细

docker inspect命令返回的是一个Json格式的消息,获取其中一项内容可以使用-f参数指定。获取镜像的Created信息。

1
sudo docker inspect [image id] -f {{".Created"}}
查看镜像创建时间查看镜像创建时间

在指定镜像ID的时候,同常使用该ID的前若干个字符组成的可区分字符串来代替完整的ID

搜寻镜像

使用docker search命令可以搜寻远端仓库中共享的镜像。

1
sudo docker search [item]

可选参数
–automated=false 仅显示自动创建的镜像。
–no-trunc=false 输出信息不截断显示
-s,–starts=0 指定仅显示评级未指定星级以上的镜像


搜寻镜像搜寻镜像

name 镜像的名字
description 描述
stars 星级
official 是否官方创建
automated 是否自动创建

删除镜像

1
sudo docker images rm [image id|tag]

或者

1
sudo docker rmi [image id|tag]
删除镜像删除镜像

强行删除镜像可以使用-f参数。

1
sudo docker images rm [image id tag] -f

创建镜像

创建镜像的方法有三种:基于已有镜像的容器创建、基于本地模板导入、基于Dockerfile创建。

基于已有镜像的容器创建

主要使用docker commit命令。

1
sudo docker commit [options] container [repository[:tag]]

可选参数
-a,–author=”” 作者信息。
-m,–message=”” 提交消息。
-p,–pause=true 提交时暂停容器运行。

演示。首先,启动一个镜像,并且在其中进行修改操作,创建test文件,之后退出。

1
2
3
4
king@ubuntu ~ sudo docker run -it ubuntu /bin/bash
root@d12bc42d52bc:/ touch test
root@d12bc42d52bc:/ exit
exit

容器的ID为d12bc42d52bc。

提交镜像。

1
2
king@ubuntu ~ sudo docker commit -m "Added a new file" -a "Docker Newbee" d12bc42d52bc test
sha256:1150ce2e62f8ddb58c2fea2de546636d3d7fee0793483f7ecb56c30b3a5bf3fc

此时查看本地镜像列表,可以看到新创建的镜像。

基于本地模板导入

从一个操作系统模板文件导入一个镜像。这里使用的是OpenVZ提供的模板来创建。
下载地址

1
sudo docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

基于Dockerfile创建

[下节讲]

存储和载入镜像

存储镜像

1
sudo docker save [OPTIONS] IMAGE [IMAGE...]

可选参数
-o, –output string 写到文件中。


载入镜像

1
sudo docker load [OPTIONS]

可选参数
-i, –input string 文件名。
-q, –quiet Suppress the load output.


上传镜像

可以使用docker push命令上传镜像到仓库,默认上传到DockerHub官方仓库(需要登录)。

1
sudo docker push [OPTIONS] NAME[:TAG]

Docker容器

容器是Docker的另一核心概念。容器是镜像的一个运行实例,不同的是,容器带有额外的可写文件层。

创建容器

新建容器

可以使用docker create命令新建一个容器。

1
sudo docker create [OPTIONS] IMAGE [COMMAND] [ARG...]

使用docker create命令创建的容器处于停止状态,可以使用docker start命令来启动它。

1
sudo docker start [OPTIONS] CONTAINER [CONTAINER...]

新建并启动容器

启动容器有两种方式:一种是基于镜像新建一个容器并启动,另一个是将在终止的状态(stopped)的容器重新启动。使用命令docker run,等价于先执行docker create命令,再执行docker start命令。

1
sudo docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

当利用docker run来创建并启动容器是,Docker在后台运行的标准包括:

  1. 检查本地是否存在指定的镜像,不存在就从公有仓库下载。
  2. 利用镜像创建并启动一个容器。
  3. 分配一个文件系统,并在只读的镜像层外面挂在一层可读写层。
  4. 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中。
  5. 从地址池配置一个IP地址给容器。
  6. 执行用户指定的应用程序。
  7. 执行完毕后容器就被终止。

下面的命令将启动一个bash终端,允许用户进行交互。

1
sudo docker run -t -i ubuntu /bin/bash

可选参数
-t docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上。
-i 容器的标准输入保持打开。

用户可以使用Ctrl+d或者exit命令退出容器。
对于创建的bash容器,当使用exit命令退出后,该容器就会自动处于中止状态。
因为对于docker容器来说,当运行的应用退出后,容器也就没有了继续运行的必要了。

守护态运行

更多时候,需要docker容器在后台以守护态(Daemonized)形式运行。用户可以添加-d参数来实现。

1
sudo docker run -d ubuntu /bin/sh -c "while ture; do echo hello world; sleep 1; done"

ps:要获取容器的输出信息可以通过docker logs命令

1
sudo docker logs [OPTIONS] CONTAINER

终止容器

1
sudo docker stop [OPTIONS] CONTAINER [CONTAINER...]

可选参数
-t,–time=10 等待几秒停止。首先会向容器发送SIGTERM信号,等待t秒后,再发送SIGKILL信号终止容器。

docker kill命令会直接发送SIGKILL信号强行终止容器。

docker start命令可以重新启动已经终止的容器。
docker restart命令将会让一个运行的容器终止,然后重新启动。

进入容器

在使用-d参数时,容器启动后会进入后台,用户需要进入容器进行相关操作。

attach命令

docker attach是docker自带的命令。

1
sudo docker attach [OPTIONS] CONTAINER

但是使用attach命令有时并不方便。
当多个窗口同时attach到同一容器是,所有窗口都会同步显示。
当某个窗口因为命令阻塞时,其他窗口也无法执行操作了。

exec命令

docker自1.3版本起,提供一个更加方便的工具exec,可以直接在容器内运行命令。

1
sudo docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

nsenter工具

这里不做讨论。

删除容器

1
sudo docker rm [OPTIONS] CONTAINER [CONTAINER...]

可选参数
-f,–force=false 强行终止并删除一个运行中的容器。
-l,–link=false 删除容器的连接,但保留容器。
-v,–volumes=false 删除容器挂载的数据卷。


删除运行中的容器可以添加-f参数。docker会发送SIGKILL信号给容器,终止其中的应用。

导入和导出容器

导出容器

导出容器是指导出一个已经创建的容器到一个文件中。

1
sudo docker export [OPTIONS] CONTAINER

导入容器

导出的文件又可以使用docker import命令导入,成为镜像。

1
sudo docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

docker load和docker import比较。
docker load导入镜像存储文件到本地镜像库。
docker import导入容器快照到本地镜像库。
区别在于容器快照文件将丢弃所有的历史记录和元数据信息(仅保存容器当时的快照状态),而镜像存储文件将保存完整信息,体积也要大。

Docker仓库

仓库(Repository)是集中存放镜像的地方。注册服务器是存放仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下有多个镜像。对于仓库地址dl.dockerpool.com/ubuntu来说,dl.dockerpool.com是注册服务器地址,ubuntu是仓库名。

Docker Hub

官网

创建和使用私有仓库

使用registry镜像创建私有仓库

可以使用官方提供的registry镜像来搭建本地私有仓库环境。

1
sudo docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry

此时本地将启动一个私有仓库服务,监听端口为5000。

默认情况下,会将仓库创建在容器的/tmp/registry下。
可以通过-v参数来将镜像文件存放在本地的指定路径上。

管理私有仓库镜像

使用docker tag将ubuntu镜像标记为10.211.55.11:5000/test(格式为docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG])

1
2
sudo docker tag ubuntu 10.211.55.11:5000/king
sudo docker images

10.211.55.11是我的IP地址。


使用docker push上传标记的镜像。

1
sudo docker push 10.211.55.11:5000/king

现在可以在任意连接到10.211.55.11的机器下载这个镜像。

1
sudo docker pull 10.211.55.11:5000/king

出现错误

1
2
3
king@ubuntu: sudo docker push 10.211.55.11:5000/king
The push refers to repository [10.211.55.11:5000/king]
Get https://10.211.55.11:5000/v2/: http: server gave HTTP response to HTTPS client

在/etc/docker下,创建daemon.json文件。

1
{ "insecure-registries":["10.211.55.11:5000"]}

重启docker

1
systemctl restart docker.service

重新启动registry

1
2
sudo docker ps -a # 找到registry的CONTAINER ID
sudo docker start [CONTAINER ID]