课程介绍

“终于写完了这个项目,可是部署配置环境也好麻烦啊!”“穷学生,想学习分布式,没那么多电脑,自己电脑又没办法开很多虚拟机……”

不知道你有没有类似的问题?如果有的话,那么这个教程一定适合你!

Docker 可以把 Linux 系统像集装箱一样封装起来运行,就好像虚拟机一样,并且额外开销很低,一台笔记本几十个“虚拟机”不成问题;速度快,毫秒级启动。最重要的是,你只需要配置一次环境就可以到处运行。

本课程主要面向零基础 Docker 用户,对于初学者而言,学习 Docker 的最大障碍不是网上资源太少,而是网上资源太多。本课将摒除噪音,只给你最实用的操作指南。无论你是后端开发、运维,还是机器学习者,学习 Docker 将大大提高你的工作效率。

作者简介

张仕超,机器学习与辅助驾驶方向研究生,本研期间参加过多个相关领域国际赛事(RoboCup,类脑计算等)并取得优异成绩。乐于分享,擅长用简明清晰的语言讲述复杂艰深的知识。

课程内容
第01课:初遇 Docker

Docker 是什么?

先来点通俗的解释:

“Docker”这个单词有“码头工人”的意思,码头工人的工作就是把货物装到集装箱里,然后把集装箱搬到货船上面。Docker 就是借鉴了这种做法,想一想,集装箱有什么好处呢?在一艘大货船上,所有货物装成集装箱就可以方便快捷地摆放在一起,并且各种各样的集装箱的规格都被标准化了,不管货物是什么,只要装到集装箱里面,就可以一次性被运走,而不必把不同的货物分开运输。

enter image description here

Docker 就使用了这种思想。Docker 就像一个码头工人,把可以运行的 Linux 系统装载到一个个容器(container)里,这些容器就像一个个“装载了 Linux 系统”的集装箱。就像每个集装箱都有自己的货物一样,每个容器都像一个独立的 Linux 系统一样可以运行指定的程序。比如,一个容器可以作为 Web 服务器,另一个容器作为数据库服务器。

集装箱之间互不影响。同样,容器之间也都是独立的,一个容器不能操作另一个容器的资源,因此可以很好地隔离运行环境。每个容器都像一个独立的操作系统,拥有操作系统运行需要的所有配置和代码。

下面是更官方的解释:

Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于2013年3月以 Apache2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。

Docker 使用 Google 公司推出的 Go 语言进行开发和实现,在 Linux 操作系统上提供了一个软件抽象层和操作系统层虚拟化的自动管理机制。Docker 利用了 Linux 的资源分托机制(cgroups 以及命名空间)来创建独立的软件容器。Linux 对命名空间的支持完全隔离工作环境中的应用程序,包括进程树,网络,用户 ID 与挂载文件系统;而 cgroups 则提供了资源隔离,包括 CPU,内存等。Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大简化了容器的创建和维护,使得 Docker 技术比虚拟机技术更为轻便快捷。

enter image description here

图 linux 小企鹅,Go 小熊以及好多朋友参与 Docker 的海上豪华生日 Party。

Docker 可以解决虚拟机能够解决的问题,也可以解决虚拟机由于资源要求过高而无法解决的问题。

  • 隔离应用依赖
  • 创建应用镜像并复制
  • 创建易于分发的即开即用的应用或者应用镜像
  • 允许实例简单快速扩展
  • 易于测试和销毁

Docker 的初衷是创建软件程序可移植的轻量容器,让软件可以在任何安装了 Docker 的主机上运行,而不用关心底层操作系统。

Docker 重要概念

Docker 镜像(Image)

通俗解释: 镜像类似于一个系统安装光盘,你可以使用一个安装光盘为多台电脑安装操作系统,同样,你也可以用同一个镜像构建多个运行的 Docker 实体——容器(容器的概念参见本文3.2小节)。当你使用同一张安装光盘给多台电脑安装系统之后,这些电脑的系统是完全一样的,换句话说,安装光盘的内容是不变的。同理,镜像也是一个静态的概念,从同一个镜像运行的 Docker 容器也都是一样的,镜像的内容在生成之后就不再改变!

专业一点的解释: Docker 镜像是一个特殊的文件系统,类似于 Linux 的 root 文件系统,镜像提供了容器运行时所需的程序、库、资源、配置等文件,还包含了一些为运行时准备的一些配置参数。镜像是一个静态的概念,镜像不包含任何动态数据,其内容在构建之后也不会被改变。

由于镜像包含完整的 Linux root 文件系统,所以它可能会很庞大。因此,Docker 的设计者充分利用 Unions FS 技术,把 Docker 设计为分层存储的结构,什么意思呢?

意思是说,镜像是分层构建的,每一层是上面一层的基础,每一层在构建完成之后都不会再发生变化,这提醒我们,构建镜像的时候我们要保证每一层都只包含我们的应用需要的东西,不要有包含不需要的文件,因为每一层在构建之后不再发生变化,所以即使你在之上的层删除了那些不需要的文件,这些文件也只是被标记为删除,实际上并没有真正删除;如果每一层都包含一些可有可无的文件,就会使得我们的镜像越来越臃肿。通过之前的叙述,我们可以看出,一个镜像实际上并不是一个文件,而是一组分层文件。分层存储还使得不同的镜像可以共享某些层,便于镜像的复用。

备注:更多具体关于命名空间和分层存储的知识会在后面的教程详细说明,所以即使现在不能完全理解也可以放心地继续阅读。

Docker 容器(Container)

你可以从镜像创建容器,就像从快照创建虚拟机一样。容器是一个动态的概念,你的程序都是在容器里运行的。

容器就是一个进程,但是它有自己独立的命名空间,拥有自己独立的文件系统,独立的网络等资源。因此,容器就好像一个完全独立于宿主主机的操作系统一样,完全可以被当做一个独立的操作系统使用。

容器也是分层存储的,当你从一个镜像创建并运行一个容器的时候,是以镜像作为基础层,在此之上创建一个容器的存储层,你对容器的读写都是在这一层完成的。但是当容器消亡的时候,容器的存储层也会随之消失。因此,我们不应该在容器的存储层写入数据,文件的写入操作需要使用其它的方式,这会在之后的教程介绍。

我们现在只需要知道,容器和镜像都是分层存储的,并了解容器和镜像的关系就足够了!随着教程的深入,我们会一步步学习更加具体的内容。

Docker 仓库(Registry)

Docker 仓库是一个集中存储和分发镜像的服务,你可以建立自己的私有仓库,也可以使用共有仓库,比如 Docker Store。你可以从仓库里搜索你需要的镜像,也可以把你自己构建的镜像分享到仓库供别人下载使用。

为什么使用 Docker?

Docker 是一种新兴的虚拟化方式,在第3节我们会把 Docker 和虚拟机类比,但是,Docker 不是虚拟机,传统的虚拟机是先虚拟硬件资源,然后在虚拟的硬件资源之上运行操作系统。而 Docker 容器作为一个进程,直接运行于宿主主机内核,因此 Docker 更加快捷,下图是虚拟机和 Docker 的对比:

enter image description here图片来自网络

正是由于这些不同,使得 Docker 具有很多优势:

  • 高效利用系统资源(没有虚拟硬件的额外开销)。
  • 更快的启动时间(通常可以在1秒内启动)。
  • 便于部署(镜像包含了应用和相关依赖,可以运行在任何配置了 Docker 的主机上)。
  • 轻松迁移。
  • 分层存储,提高存储效率。

接下来做什么?

现在我们已经对 Docker 有了一个基础的认识,接下来的教程,我们会先介绍(复习)一下 Linux 的基本命令,然后从安装 Docker 开始,一步一步学习 Docker 的基本使用。

说明

本课程写作过程中参考了一些网络资源,参考资源的链接在此一并列出:

第02课:面向新手-Linux 命令行初探

虽然学习使用 Docker 的读者应该都具备了这些基础知识,但是为了教程的完整性,我还是希望添加这部分内容。如果你熟悉这些命令,可以跳过本文阅读后面的内容。如果你真的是小白,那么这就是为你准备的!

Linux 的安装与使用

如果你是 Linux 新手,我推荐先使用 Linux 虚拟机来熟悉 Linux 系统。

使用 VMware 安装 Ubuntu 系统的教程参考这里,或者你也可以自行搜索安装步骤。

如果你只是为了学习 Docker,不想在自己的电脑上安装虚拟机或者双系统,可以先跳过本文,待后面用到相关指令的时候再来查询。

安装好之后打开虚拟机,使用“Alt+Ctrl+T”按键打开终端模拟器。

打开终端后,提示符形式如下:

zsc@Berry:~$ 

其中 zsc 是用户名,Berry 是主机名,~代表用户 home 目录,含义是“/home/zsc/”,表示我们现在在此目录下工作。

基本的 Linux 命令

  • ls

ls 的作用是列出当前目录下的文件。在终端模拟器输入 ls,会得到如下输出(你得到的结果和我的结果会有所不同):

zsc@Berry:~$ lsberry.pem  Music  tensorflow    workspace

ls 命令有好多参数,常用的参数是 -a(同时列出隐含文件),-l(输出一个比较完整的格式,除每个文件名外,增加显示文件类型、权限、硬链接数、所有者名、组名、大小(byte)、及时间信息)。

zsc@Berry:~$ ls -a.                   .gnupg             .python_history..                  .graphlab          .remarkable.adobe              .gvfs              .ros.android            .ICEauthority      s3637077
zsc@Berry:~$ ls -ltotal 72-r--------  1 zsc zsc 1692 Mar  1 20:29 berry.pem-rw-rw-r--  1 zsc zsc 1692 Mar  8 19:52 berry_s3637077.pemdrwxr-xr-x  2 zsc zsc 4096 Jun  7 18:00 Desktopdrwxr-xr-x  9 zsc zsc 4096 May 19 10:34 Documentsdrwxr-xr-x 12 zsc zsc 4096 Jun 24 13:27 Downloadsdrwx------  8 zsc zsc 4096 Jun 21 23:00 我的坚果云
  • mkdir 新建目录

例子:mkdir test 命令会在当前目录下建立一个名为“test”的新目录。

  • touch 创建文件

例子:在 test 目录下创建 readme.txt文件:

zsc@Berry:~$ touch test/readme.txt
  • cd 命令切换目录

例子:由之前的 ls 命令的输出,可以看到我的目录下有 workspace 这个目录,执行“cd workspace”可以切换到这个目录:

zsc@Berry:~$ cd workspace/zsc@Berry:~/workspace$ 

你会发现切换目录后提示符已经变成了“~/workspace”而不是原来的“~”。

  • pwd 显示当前目录

例子:由于之前执行了“cd workspace”命令,因此现在我们处在 workspace 目录下。

zsc@Berry:~/workspace$ pwd/home/zsc/workspace
  • mv 命令移动文件

格式:mv source destination

比如我想把当前目录 /home/zsc 下的 s3637077 文件移动到 workspace 目录下:

zsc@Berry:~$ mv s3637077 workspace/

mv 命令除了可以移动文件还可以给文件重命名,比如我想把 s3637077 文件重命名为 test:

zsc@Berry:~$ mv s3637077 test
  • cp 复制文件

格式:cp source destination

例子:比如我想把 s3637077 复制到 workspace 文件夹下(由于之前使用过 mv 命令把 s3637077 移动到了 workspace 文件夹下,所以现在当前目录是没有 s3637077 这个文件了,为了演示命令效果,我又新建了一个 s3637077 同名文件,这用到了“touch s3637077”命令):

zsc@Berry:~$ cp -i s3637077 workspace/cp: overwrite 'workspace/s3637077'? 

注意,这里的 -i 参数表示在执行命令的时候询问是否覆盖文件(我们之前用 mv 命令已经在 workspace 目录下放置了一个同名文件,因此会提示),建议养成使用 -i 参数的好习惯(包括 mv 命令也支持 -i 参数)。输入 y 则覆盖。

同时,cp 命令支持递归复制,使用 -r 参数复制一个目录及其子目录到目标位置:

"cp -ir test/ workspace"(递归复制 test 目录到 workpace 目录下并在覆盖时提示。)

  • rm 删除文件

格式:rm file

例子:删除 test 目录下的 readme.txt 文件:

zsc@Berry:~$ rm -i test/reamde.txt

支持 -r 参数递归删除目录及其子目录:

zsc@Berry:~$ rm -ir test/

(注意使用 i 参数进行确认提示,因为使用 rm 命令删除后是不可恢复的,因此删除文件需要特别小心。)

Tips:对于初学者,使用命令行很容易输错命令、目录名或者文件名,实际上,在目录名和文件名很长的情况下打字错误发生的概率还是很高的。因此,Linux 为我们准备了自动补全功能,使用 Tab 键实现,比如,我们想切换到 workspace 目录,输入:

zsc@Berry:~$ cd wor

然后按下 Tab 键就会自动补全为 cd workspace/ 如果我们还有一个 workspace2 目录,那么按下两次 Tab 键后会给出可选的操作:

zsc@Berry:~$ cd workspaceworkspace/  workspace2/ 

然后我们可以继续输入想要的进入的目录。

归档与压缩数据

压缩数据

Linux 有多种文件压缩工具,这听上去可能不错,但是初学者常常感觉有些混乱。下表是 Linux 常见的文件压缩工具(表格翻译自 Linux Command Line and Shell Scripting Bible, 3E, Richard Blum):

工具文件扩展名描述
bzip2.bz2采用 Burrows-Wheeler 块排序文本压缩算法和霍夫曼编码
compress.Z最初的 Unix 压缩工具,现在已经很少使用
gzip.gzGNU 压缩工具
zip.zipWindows 的压缩算法的 Linux 实现

这里主要介绍一下 ZIP 工具。

  • 压缩文件

zip target.zip filename

  • 压缩文件夹

zip -r target.zip dir -r 参数表示递归压缩子目录

  • 解压

unzip target.zip

归档数据

压缩和解压缩并不是标准的 Linux 归档工具,目前,Linux 和 Unix 上使用最广泛的归档工具是 tar 命令。

格式:tar function [options] object1 object2

具体参数请参考命令手册(在本文最后有命令手册的使用介绍)。由于本文是补充内容,因此无法面面俱到,这里我仅仅介绍最常用的方法:

比如我们下载了一个文件叫做 test.tar。

使用命令:tar -xvf test.tar 就可以把归档文件里的内容提取到当前文件夹。其中,-x 参数表示从已有的归档文件提取文件,-v 参数表示在处理文件时显示文件,-f 表示输出结果到文件。

网络命令

  • ping 命令检查网络是否可连接
zsc@Berry:~$ ping www.google.comPING www.google.com (216.58.199.36) 56(84) bytes of data.64 bytes from www.google.com (216.58.199.36): icmp_seq=1 ttl=56 time=19.8 ms64 bytes from www.google.com (216.58.199.36): icmp_seq=2 ttl=56 time=16.9 ms64 bytes from www.google.com (216.58.199.36): icmp_seq=3 ttl=56 time=16.5 ms64 bytes from www.google.com (216.58.199.36): icmp_seq=4 ttl=56 time=16.8 ms64 bytes from www.google.com (216.58.199.36): icmp_seq=5 ttl=56 time=17.9 ms^C--- www.google.com ping statistics ---5 packets transmitted, 5 received, 0% packet loss, time 4006msrtt min/avg/max/mdev = 16.504/17.625/19.891/1.237 mszsc@Berry:~$ 
  • ifconfig 查看本机网路
zsc@Berry:~$ ifconfig br-67f29ac07de2 Link encap:Ethernet  HWaddr 02:42:a2:41:20:63            inet addr:172.18.0.1  Bcast:0.0.0.0  Mask:255.255.0.0          UP BROADCAST MULTICAST  MTU:1500  Metric:1          RX packets:0 errors:0 dropped:0 overruns:0 frame:0          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)docker0   Link encap:Ethernet  HWaddr 02:42:5c:9b:03:82            inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0          UP BROADCAST MULTICAST  MTU:1500  Metric:1          RX packets:0 errors:0 dropped:0 overruns:0 frame:0          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)enp3s0    Link encap:Ethernet  HWaddr 3c:97:0e:d9:83:85            UP BROADCAST MULTICAST  MTU:1500  Metric:1          RX packets:0 errors:0 dropped:0 overruns:0 frame:0          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:1000           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)          Interrupt:19 lo        Link encap:Local Loopback            inet addr:127.0.0.1  Mask:255.0.0.0          inet6 addr: ::1/128 Scope:Host          UP LOOPBACK RUNNING  MTU:65536  Metric:1          RX packets:36995 errors:0 dropped:0 overruns:0 frame:0          TX packets:36995 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:1           RX bytes:1989010 (1.9 MB)  TX bytes:1989010 (1.9 MB)wlp2s0    Link encap:Ethernet  HWaddr 40:f0:2f:43:87:dc            inet addr:192.168.1.102  Bcast:192.168.1.255  Mask:255.255.255.0          inet6 addr: fe80::1870:2281:a509:aea6/64 Scope:Link          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1          RX packets:50860 errors:0 dropped:0 overruns:0 frame:0          TX packets:46602 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:1000           RX bytes:31656934 (31.6 MB)  TX bytes:24497523 (24.4 MB)zsc@Berry:~$ 
  • wget 下载文件

“wget url”下载文件到当前目录。

环境变量

Bash Shell(Ubuntu 系统的启动 shell 默认是 Dash shell,但是交互式 shell 也就是你使用终端模拟器的时候默认是 Bash shell)。使用一个叫做环境变量的特性来存储有关 shell 会话和工作环境的信息。环境变量分为局部变量和全局变量。

本文对环境变量不做过多介绍。在后续教程用到的地方会详细说明。

安装和卸载软件

  • 更新软件列表(只会检测更新,不会安装更新)
sudo apt-get update
  • 更新软件(会安装更新)
sudo apt-get upgrade
  • 安装软件
sudo apt-get install zipsudo apt-get install unzip

  或者写在一起:

sudo apt-get install zip unzip
  • 卸载软件
sudo apt-get remove zip unzip
  • 自动修复依赖项

有时候安装软件会出现依赖项不满足的情况,此时使用

sudo apt-get install -f

可以修复依赖项。一般情况下此命令可以有效修复依赖性,如果不行的话,需要对照错误信息手动修复。

  • 其它

如果 apt-get 无法找到对应的软件,则需要下载对应的“.deb”安装包来进行安装,比如下载了“test.deb”,使用 dpkg 安装,-i 参数表示 install,-r 参数表示卸载移除。

sudo dpkg -i test.deb

使用编辑器

Gedit 图形编辑器

Gedit 和 Windows 的记事本差不多,可以点击屏幕左上角图标,搜索 Gedit 打开,或者在终端模拟器输入 Gedit 回车打开。由于图形化的操作和 Windows 很相似,所以不再详细介绍。

vim

vi 是 Unix 系统最初的编辑器,之后 GNU 项目将 vi 移植到了开源世界,在此过程中,GNU 对最初的 vi 做了一些改进,于是就有了 vim(vi improved),vim 可能是现在最繁琐也最强大的编辑器。本节介绍一些基本用法,以便我们可以在 vim 里活下来。

首先,使用“sudo apt-get install vim”安装 vim。

安装好之后就可以使用了。当前目录有一个 test.cpp 文件,我们对这个文件使用 vim 进行编辑。

vim test.cpp

vim 有两种模式,一种是普通模式,另一种是插入模式。执行上述命令以后进入普通模式。按下字母键“i”进入插入模式,使用方向键移动光标到需要插入的位置,然后输入想要插入的内容。编辑完成后按键“Esc”退出回到普通模式。

在普通模式下输入冒号“:”,然后输入 w 回车,保存更改。接着输入“:q”退出。也可以直接输入“:wq”保存并退出(注意 w 一定要在 q 之前,先保存再退出)。

这里写图片描述

其它基本命令

查找:在普通模式下输入“/stringToFind”,回车,即可定位到第一个匹配项。接着按下字母键“n”可以查找下一个。

撤销:普通模式下输入“:u”并回车,实现撤销。

以上就是一些最基本的命令,了解了基本命令可以让我们不至于排斥这个编辑器,慢慢探索 vim 更多的功能。因为如果你使用远程服务器编辑文本的话是没有办法得到图形界面的,在这种情况下,vim 是一个很好的选择。

其它编辑器

Linux 上的编辑器有很多,无论是图形界面的还是命令行形式的,你可以找到自己喜欢的编辑器。图形界面的编辑器除了自带的 Gedit,更推荐 sublime 或者 atom,有兴趣的可以搜一下。命令行形式的编辑器还是推荐 vim。  

更多

本文仅仅是介绍了一些 Linux 的入门用法,掌握这些命令之后,Linux 新手用户基本可以在 Linux 环境下生存下来。如果想要学习更多的相关知识,比如权限管理,文件系统管理……可以买一些书或者一些网络教程,比如http://www.runoob.com/linux/linux-system-contents.html 就是一个是不错的教程。

同时,学会使用 Bash 手册也有助于你学习 Linux 命令。Bash 手册默认是英文的(即使你安装系统的时候选择中文语言),如果你阅读英文不是很流利,可以参照以下步骤把手册变为中文:

首先,下载中文包:

sudo apt-get install manpages-zh

之后,编辑 man 配置文件:

sudo vim /etc/manpath.config

将此文件里所有的 /usr/share/man 替换为 /usr/share/man/zh_CN

完成之后来看一下效果,输入“man mv”:

这里写图片描述  

第03课:安装 Docker 到你的电脑
第04课:Docker 使用入门(上)
第05课:Docker使用入门(下)
第06课:学习编写 Dockerfile
第07课:Docker 底层原理初探
第08课:用 Docker 建立一个公用 GPU 服务器
第09课:后记-Docker 生态

阅读全文: http://gitbook.cn/gitchat/column/5a13be9775462408e0da8d9d

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐