初识Docker

本文是我初步了解Docker技术的笔记

什么是Docker?

Docker 是能够对进程进行封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。

enter description here

enter description here

相比传统的虚拟化技术Docker有许多的优点:更高效的利用系统资源;更快速的启动时间;一致的运行环境;持续交付和部署;更轻松的迁移;更轻松的维护和扩展

概念

镜像(Image)

Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。

镜像是分层存储的,构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。这样使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

容器(Container)

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。

前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为容器存储层。

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

仓库(Repository)

和GitHub中的仓库类似,Docker中的仓库也是展现不同版本的镜像的地方。一个仓库包含一个软件(或者开发环境)的不同版本的镜像,标签就是对应着这些镜像的版本号。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。

与Github这种代码托管平台一样,仓库我们可以放在公共的Docker Registry中(最常用的是 Docker Hub,国内有许多高质量的镜像服务),也可以放在私有的Docker Registry中。

安装

官方安装指南在这里

Ubuntu

加载可选模块

从 Ubuntu 14.04 开始,一部分内核模块移到了可选内核模块包。AUFS 内核驱动属于可选内核模块的一部分,作为推荐的 Docker 存储层驱动,一般建议安装可选内核模块包以使用 AUFS。

1
2
3
4
5
sudo apt-get update

sudo apt-get install \
linux-image-extra-$(uname -r) \
linux-image-extra-virtual

向APT中添加源

添加使用 HTTPS 传输的软件包以及 CA 证书:

1
2
3
4
5
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common

添加软件源的 GPG 密钥(因为国内的网络问题,可以使用国内的源)

1
2
3
4
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

# 官方源
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

source.list中加入Docker软件源

1
2
3
4
5
6
7
8
9
10
11
$ sudo add-apt-repository \
"deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
$(lsb_release -cs) \
stable"


# 官方源
# $ sudo add-apt-repository \
# "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
# $(lsb_release -cs) \
# stable"

安装Docker CE

更新apt,并安装`Docker CE’:

1
2
3
$ sudo apt-get update

$ sudo apt-get install docker-ce

使用脚本自动安装

官方版:

1
curl -sSL https://get.docker.com/ | sh

阿里云安装脚本:

1
curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | sh -

DaoCloud安装脚本:

1
curl -sSL https://get.daocloud.io/docker | sh

镜像加速器

腾讯云官方给出的配置方法:
修改 Docker 配置文件 /etc/default/docker,如下:

1
DOCKER_OPTS="--registry-mirror=https://mirror.ccs.tencentyun.com"

更高效的配置:

通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

docker info测试是否配置好,查看是否有以下的信息:

1
2
Registry Mirrors:
https://mirror.ccs.tencentyun.com

Docker-compose 安装

可以参考官方文档

1
2
sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

但是我在操作上面的命令的时候会出现下载不了的错误,所以我就从官方的Github下载了最新的realease,然后复制到/usr/local/bin/

创建docker用户组

Docker守候进程绑定的是一个unix socket,而不是TCP端口。这个套接字默认的属主是root,其他是用户可以使用sudo命令来访问这个套接字文件。因为这个原因,docker服务进程都是以root帐号的身份运行的。

为了避免每次运行docker命令的时候都需要输入sudo,可以创建一个docker用户组,并把相应的用户添加到这个分组里面。当docker进程启动的时候,会设置该套接字可以被docker这个分组的用户读写。这样只要是在docker这个组里面的用户就可以直接执行docker命令了。

警告:该dockergroup等同于root帐号,具体的详情可以参考这篇文章:Docker Daemon Attack Surface

sudo usermod -aG docker your_username

镜像操作

获取镜像

获取镜像的格式是:

1
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

具体的帮助文档可以通过docker pull --help查看
参数解释:

  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。

运行测试:

1
$ sudo docker run -it --rm ubuntu:16.04 bash

参数解释:

  • -it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
  • –rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。我们这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 –rm 可以避免浪费空间。
  • ubuntu:16.04:这是指用 ubuntu:16.04 镜像为基础来启动容器。
  • bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 bash。

列出镜像

一般使用的使用的是docker image ls或者docker images 指令
可以使用相应的--help查看帮助

制作镜像

当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 docker commit 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。

docker commit语法格式:

1
2
3
4
5
6
7
8
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]

# 例子
$ docker commit \
--author "Tao Wang <twang2218@gmail.com>" \
--message "修改了默认网页" \
webserver \
nginx:v2

可以搭配docker diff查看容器当前的修改和docker history查看镜像的相关历史记录

注意:慎用docker commit操作:

使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体在操作的。虽然 docker diff 或许可以告诉得到一些线索,但是远远不到可以确保生成一致镜像的地步。这种黑箱镜像的维护工作是非常痛苦的。

推送镜像

当你需要把本地制作的镜像推送到远端仓库中,你就可以使用docker push命令,这个命令默认推送到的是Docker的官方镜像仓库:Docker Hub。

在推送之前,你需要在Docker Hub中创建好相应的image并登录:docker login [OPTIONS] [SERVER]

然后使用push命令推送:

1
docker push [OPTIONS] NAME[:TAG]

例子:

1
2
3
4
5
$ docker commit c16378f943fe rhel-httpd

$ docker tag rhel-httpd registry-host:5000/myadmin/rhel-httpd

$ docker push registry-host:5000/myadmin/rhel-httpd

参考:
博客1

  • 本文作者: Sixzeroo
  • 本文链接: https://www.liuin.cn/2017/12/10/初识Docker/
  • 发布时间: 2017年12月10日 - 20时12分
  • 最后更新: 2019年1月6日 - 14时01分
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!