Docker概述
- Go语言开发
- 基于LXC(LinuX Containers),以及 AUFS 类的 Union FS 等技术
- 从文件系统、网络互联、进程隔离等方面对进程进行封装隔离
- 属于操作系统层面的虚拟化技术
- 由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器
- 单一容器或单一服务器的一组容器都不再是关注的重点,如何通过云原生应用(Cloud Native Application)和微服务框架(Microservice Framework),把商业逻辑映射为容器集群,为商业成功奠定技术基础才是核心。
特点
官方总结了Docker的6个特点,也可以说是优势,包括:
- Flexible 灵活
- Lightweight 轻量
- Portable 可移植
- Loosely coupled 松耦合
- Scalable 可扩展
- Secure 安全
理解
James Turnbull在书[1]中将Docker容器总结为:
- 一个镜像格式
- 一系列标准的操作
- 一个执行环境
如果将容器看做码头上的标准的集装箱,镜像格式就是集装箱的打包标准;由于镜像是由若干指令一步一步构建而成的,因此也可以看做一系列标准操作的集合;集装箱的目的是为了储存转运货物,而容器的目的是运行软件,我们使用集装箱的目的是提供一个能够保障货物储存的集装箱条件,在Docker容器中,我们为软件产品提供了配套的执行环境。
[1] THE DOCKER BOOK, James Turnbull, https://dockerbook.com.
Docker与VM不同
最主要:避免虚拟机中的guestOS
传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
Docker常见名词
镜像Image
docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
容器Container
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
仓库Registry
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
Docker安装
在Linux系统上可以直接安装Docker,但是在OS X系统和Windows系统中应该使用Docker Toolbox工具安装Docker。
不是基于Linux内核的系统如何运行Docker?
Docker Toolbox集合安装了运行Docker所需的所有组件,包括VirtualBox和一个极小的虚拟机,并提供了一个包装脚本(wrapper script)对虚拟机进行管理。
虚拟机在OS X和Windows系统中提供一个本地的守护进程(Docker daemon running);同时,Docker客户端作为OS X和Windows系统的原生程序被安装,并连接到虚拟机中的守护进程中。
官方文档https://docs.docker.com/install/linux/docker-ce/ubuntu/
安装条件
- 64位CPU构架的计算机
- 运行Linux 3.8以上内核
- 内核须开启cgroup和namespace功能
- 适合的存储驱动(storage driver)
docker在ubuntu上支持overlay2,aufs和btrfs三种storage drivers,其中,btrfs仅支持企业版Docker的SLES;overlay2是默认的也是官方推荐的一种。
版本介绍
docker有两个版本:
- docker-ce(社区版)
- docker-ee(企业版)
这里介绍安装社区版,也就是docker-ce。
安装
- 卸载旧版本
$ apt-get remove docker docker-engine docker.iod runc
- 通过repository安装
# 检查内核
$ uname -a
# 检查存储管理
$ ls -l /sys/class/misc/device-mapper
# 更新源
$ apt-get update && apt-get upgrade
# 安装必备软件
$ apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
# 添加Docker官方 GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 验证key
$ apt-key fingerprint 0EBFCD88
# 查询系统版本
$ lsb_release -a
# 设置repository,以Ubuntu18.04为例,codename为bionic
$ add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
bionic \
stable"
# 安装Docker
$ apt-get install docker-ce docker-ce-clid.io
# 查看docker信息
$ docker info
# 查看docker运行状态
$ service docker status
# 开启/关闭/重启Docker
$ service docker start/stop/restart
- 更换阿里源
为了加速Docker下载镜像的速度,可以更换阿里源.
阿里云-容器镜像服务-镜像中心-镜像加速器中获取加速器地址.
$ vim /etc/docker/daemon.json
添加以下配置:
{
"registry-mirrors": ["https://wb87kbxd.mirror.aliyuncs.com"]
}
重启服务使换源生效
$ systemctl daemon-reload && systemctl restart docker
卸载
$ sudo apt-get purge docker-ce
$ sudo rm -rf /var/lib/docker
建立交互式容器
这里建立了一个基于Ubuntu的容器,并启动了一个bash.
$ sudo docker run -i -t ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
5c939e3a4d10: Pull complete
c63719cdbe7a: Pull complete
19a861ea6baf: Pull complete
651c9d2d6c4f: Pull complete
Digest: sha256:8d31dad0c58f552e890d68bbfb735588b6b820a46e459672d96e585871acc110
Status: Downloaded newer image for ubuntu:latest
启动后可以看到终端已经进入了容器,前面变成了"root@6abd43f72939:/# "
查看容器主机名
root@6abd43f72939:/# hostname
6abd43f72939
查看host文件
root@6abd43f72939:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 6abd43f72939
使用net-tools查看网络配置
root@6abd43f72939:/# apt-get update
root@6abd43f72939:/# apt-get install net-tools
root@6abd43f72939:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 11535 bytes 18505969 (18.5 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 11140 bytes 1042829 (1.0 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
查看容器进程
root@6abd43f72939:/# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 18508 3504 pts/0 Ss 08:51 0:00 /bin/bash
root 260 0.0 0.0 34400 2864 pts/0 R+ 11:39 0:00 ps -aux
原生的ubuntu源下载更新的速度较慢,这里可以更换阿里源
# 备份
root@6abd43f72939:/# cp /etc/apt/sources.list /etc/apt/sources.list.bak
# 打开源文件,注释掉原有源,添加阿里源
root@6abd43f72939:/# vim /etc/apt/sources.list
# 更新
root@6abd43f72939:/# apt-get update
P.S. 阿里源如下:
deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
安装vim程序顺便验证一下换源后的有效性
root@6abd43f72939:/# apt-get install vim
退出容器
root@6abd43f72939:/# exit
exit
退出后可以通过docker ps -a查看当前系统中所有的容器,docker ps可以查看当前正在运行的容器
$ sudo docker ps -a
[sudo] password for wangfeaibn:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6abd43f72939 ubuntu "/bin/bash" 3 hours ago Exited (0) 2 minutes ago hopeful_varahamihira
如果创建时未指定,会初始化一个随机的容器name,上面通过docker ps可以看到容器名称为"hopeful_varahamihira".容器名和ID都可以唯一确定容器,但是使用容器名相对更加直观,我们一方面可以通过创建是指定name,一方面在创建后也可以通过docker rename进行更改,命名支持大小写字母,数字和_.-,正则表达式为[a-zA-Z0-9_.-]
# 指定容器名创建
$ sudo docker run --name hello_world -i -t ubuntu /bin/bash
# 重命名, rename的第一个参数可以是id,还可以是name
$ sudo docker rename [new_containerName]/[new_containerID] hello_world
容器重启.注意重启后不会像创建时自动进入创建时的会话,但是可以通过attach可以重新回到容器的会话中.
# 重启容器
$ sudo docker start hello_world
hello_world
# 容器会话附着
$ sudo docker attach hello_world
root@6abd43f72939:/#
创建守护式容器
常用的提供各种服务的容器一般为守护式容器,守护式容器daemonized可以长期运行,没有交互式会话.
# 创建守护式容器
$ sudo docker run --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
# 跟踪式日志
$ sudo docker logs -ft daemon_dave
Docker常用命令
# 查看docker运行状态
$ sudo service docker status
# 开启/关闭/重启Docker
$ sudo service docker start/stop/restart
# 查看docker信息
$ sudo docker info
# 查看所有的本地image
$ sudo docker image ls
# 删除 image
$ docker image rm [imageName]
# 查看所有容器
$ sudo docker ps -a
或者
$ sudo docker ls --all
# 新建容器
$ sudo docker run --name [containerName] -i -t ubuntu /bin/bash
# 创建但不运行容器
$ sudo docker create [containerName]
# 停止守护式容器
$ sudo docker stop [containerName]/[containerID]
# 删除容器
$ sudo docker rm [containerName]/[containerID]
# 删除所有容器,引号内返回所有容器的名称
$ sudo docker stop $(docker ps -a -q)
# 删除所有容器
$ docker rm $(docker ps -a -q)
# 删除所有数据卷
$ docker volume rm $(docker volume ls -q)
# 重启(正在运行)/启动(未运行)现有容器
$ sudo docker restart\start [containerName]/[containerID]
# 创建bash进入容器
$ docker exec -it [containerName] bash
# 查看容器进程
$ sudo docker top [containerName]/[containerID]
# docker容器统计,同时查询支持多个容器
$ sudo docker stats [containerName1] [containerName2]..
# 获取容器详细信息
$ sudo docker inspect --format='{{ .State.Status }}' [containerName]
# 获取容器某项信息
$ sudo docker inspect --format='{{ .State.Status }}' [containerName]