Docker入门到实践——简单操作
1.对比传统虚拟机总结
特性 | 容器 | 虚拟机 |
---|---|---|
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 弱于 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
2.基本概念
Docker包括三个基本概念:
- 镜像(Image)
- 容器(Container)
- 仓库(Repository)
Docker镜像
- Docker镜像就是一个只读的模板。
- 镜像可以用来创建Docker容器。
Docker容器
Docker利用容器来运行应用。
容器是从镜像创建运行实例。它可以被:
- 启动
- 开始
- 停止
- 删除
每个容器都是相互隔离的,保证安全的平台。
Docker仓库
仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含多个镜像,每个镜像有不同的标签(tag)。
仓库分为:
- 公开仓库(Public);
- 私有仓库(Private);
最大的公开仓库是 Docker Hub,存放了数量庞大的镜像供用户下载。 国内的公开仓库包括 Docker Pool 等,可以提供大陆用户更稳定快速的访问。
当用户创建了自己的镜像之后就可以使用 push 命令将它上传到公有或者私有仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。
3.CentOS系列安装Docker
安装说明URL:https://docs.docker.com/install/linux/docker-ce/centos/#set-up-the-repository
Uninstall old versions:
$ sudo yum remove docker \
docker-common \
docker-selinux \
docker-engine
Install Docker CE:
Install using the repository:
SET UP THE REPOSITORY:
1.Install required packages.
$ sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
2.安装配置docker repo源。
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
3.启用边缘并测试存储库。
$ sudo yum-config-manager --enable docker-ce-edge
$ sudo yum-config-manager --enable docker-ce-test
或者禁用:
$ sudo yum-config-manager --disable docker-ce-edge
CentOS7系统CentOS-Extras库中已带Docker,可以直接安装:
$ sudo yum install docker-ce
安装之后启动 Docker 服务,并让它随系统启动自动加载。
$ sudo systemctl start docker
4.镜像
4.1 获取镜像
可以使用 docker pull 命令来从仓库获取所需要的镜像。
4.2 列出本地镜像
使用 docker images 显示本地已有的镜像。
$ sudo docker images
REPOSITORY | TAG | IMAGE ID | CREATED | VIRTUAL SIZE |
---|---|---|---|---|
ubuntu | 12.04 | 74fe38d11401 | 4 weeks ago | 209.6 MB |
ubuntu | precise | 74fe38d11401 | 4 weeks ago | 209.6 MB |
ubuntu | 14.04 | 99ec81b80c55 | 4 weeks ago | 266 MB |
ubuntu | latest | 99ec81b80c55 | 4 weeks ago | 266 MB |
ubuntu | trusty | 99ec81b80c55 | 4 weeks ago | 266 MB |
... |
在列出信息中,可以看到几个字段信息 :
来自于哪个仓库,比如 ubuntu;
镜像的标记,比如 14.04;
它的 ID 号(唯一);
创建时间 ;
镜像大小;
其中镜像的 ID 唯一标识了镜像,注意到 ubuntu:14.04 和 ubuntu:trusty 具有相同的镜像 ID,说明它们实际上是同一镜像。
例如下面的命令指定使用镜像 ubuntu:14.04 来启动一个容器。
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
如果不指定具体的标记,则默认使用 latest 标记信息。
4.3.1 创建镜像
创建镜像有很多方法,用户可以从 Docker Hub 获取已有镜像并更新,也可以利用本地文件系统创建一个。
4.3.2 修改已有镜像
先使用下载的镜像启动容器。
$ sudo docker run -t -i training/sinatra /bin/bash
root@0b2616b0e5a8:/#
4.4 存出和载入镜像
4.4.1 存出镜像
如果要导出镜像到本地文件,可以使用docker save命令。
$ sudo docker images
REPOSITORY | TAG | IMAGE ID | CREATED | VIRTUAL SIZE |
---|---|---|---|---|
ubuntu | 14.04 | c4ff7513909d | 5 weeks ago | 225.4 MB |
$sudo docker save -o ubuntu_14.04.tar ubuntu:14.04
4.4.2 载入镜像
可以使用docker load从导出的本地文件中再导入到本地镜像库,例如:
$ sudo docker load --input ubuntu_14.04.tar
或
$ sudo docker load < ubuntu_14.04.tar
4.5 移除
4.5.1 移除本地镜像
docker rmi:移除本地镜像;
docker rm:移除容器;
注意:在删除镜像之前要先用 docker rm 删掉依赖于这个镜像的所有容器。
4.5.2 清理所有未打过标签的本地镜像
$ docker images
可以列出本地所有的镜像,其中很可能会包含有很多中间状态的未打过标签的镜像,大量占据着磁盘空间。
使用下面的命令可以清理所有未打过标签的本地镜像:
$ sudo docker rmi $(docker images -q -f "dangling=true")
其中 -q 和 -f 是缩写, 完整的命令其实可以写着下面这样,是不是更容易理解一点:
$ sudo docker rmi $(docker images --quiet --filter "dangling=true")
4.6 镜像的实现原理
Docker 镜像是怎么实现增量的修改和维护的? 每个镜像都由很多层次构成,Docker 使用 Union FS 将这些不同的层结合到一个镜像中去。
通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD 正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。 Docker 在 AUFS 上构建的容器也是利用了类似的原理。
5 Docker容器
简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用。
5.1.1 启动容器
启动容器有两种方式:
一种是基于镜像新建一个容器并启动;
另外一个是将在终止状态(stopped)的容器重新启动;
5.1.2 新建并启动
所需要的命令主要为 docker run
例如,下面的命令输出一个 “Hello World”,之后终止容器。
$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
Hello world
下面的命令则启动一个 bash 终端,允许用户进行交互:
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
root@af8bae53bdd3:/#
或
$ sudo docker run -it ubuntu:14.04 /bin/bash
root@af8bae53bdd3:/#
其中,
-t选项:让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上;
-i选项:则让容器的标准输入保持打开;
在交互模式下,用户可以通过所创建的终端来输入命令,例如
root@af8bae53bdd3:/# pwd
/
root@af8bae53bdd3:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
当利用 docker run 来创建容器时,Docker 在后台运行的标准操作包括:
检查本地是否存在指定的镜像,不存在就从公有仓库下载 ;
利用镜像创建并启动一个容器 ;
分配一个文件系统,并在只读的镜像层外面挂载一层可读写层;
从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去;
从地址池配置一个 ip 地址给容器 ;
执行用户指定的应用程序 ;
执行完毕后容器被终止;
启动已终止容器
可以利用 docker start 命令,直接将一个已经终止的容器启动运行。
容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。可以在伪终端中利用 ps 或 top 来查看进程信息。
root@ba267838cc1b:/# ps
PID TTY TIME CMD
1 ? 00:00:00 bash
11 ? 00:00:00 ps
5.2 后台(background)运行
更多的时候,需要让 Docker在后台运行而不是直接把执行命令的结果输出在当前宿主机下。此时,可以通过添加 -d 参数来实现。
下面举两个例子来说明一下。
如果不使用 -d 参数运行容器:
$ sudo docker run ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
hello world
hello world
hello world
hello world
容器会把输出的结果(STDOUT)打印到宿主机上面
如果使用了 -d 参数运行容器:
$ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
77b2dc01fe0f3f1265df143181e7b9af5e05279a884f4776ee75350ea9d8017a
此时容器会在后台运行并不会把输出的结果(STDOUT)打印到宿主机上面(输出结果可以用docker logs 查看)。
注: 容器是否会长久运行,是和docker run指定的命令有关,和 -d 参数无关。
使用 -d 参数启动后会返回一个唯一的 id,也可以通过 docker ps 命令来查看容器信息。
$ sudo docker ps
CONTAINER ID | IMAGE | COMMAND | CREATED | STATUS | PORTS NAMES |
---|---|---|---|---|---|
77b2dc01fe0f | ubuntu:14.04 | /bin/sh -c 'while tr | 2 minutes ago | Up 1 minute | agitated_wright |
要获取容器的输出信息,可以通过 docker logs 命令:
$ sudo docker logs [container ID or NAMES]
hello world
hello world
hello world
. . .
5.3 终止容器
$ docker stop
此外,当Docker容器中指定的应用终结时,容器也自动终止。 例如对于上一章节中只启动了一个终端的容器,用户通过 exit 命令或 Ctrl+d 来退出终端时,所创建的容器立刻终止。
处于终止状态的容器,可以通过 docker start 命令来重新启动。
此外,docker restart 命令会将一个运行态的容器终止,然后再重新启动它。
5.4 进入容器
在使用 -d 参数时,容器启动后会进入后台。 某些时候需要进入容器进行操作,有很多种方法,包括使用 docker attach 命令或 nsenter 工具等。
5.4.1 attach 命令
docker attach 是Docker自带的命令。下面示例如何使用该命令。
$ sudo docker run -idt ubuntu
243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550
$ sudo docker ps
CONTAINER ID | IMAGE | COMMAND | CREATED | STATUS | PORTS NAMES |
---|---|---|---|---|---|
243c32535da7 | ubuntu:latest | "/bin/bash" | 18 seconds ago | Up 17 seconds | nostalgic_hypatia |
$sudo docker attach nostalgic_hypatia
root@243c32535da7:/#
但是使用 attach 命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。