Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
ist0ne committed Mar 28, 2019
1 parent 182d769 commit 60501ba
Show file tree
Hide file tree
Showing 8 changed files with 1,637 additions and 2 deletions.
98 changes: 98 additions & 0 deletions 1.Hello-Docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: Hello Docker
date: 2018-06-07 18:41:33
tags: [docker, container]
---
## 环境选择

容器需要管理工具、运行时和操作系统,我们的选择如下:

- 管理工具 - Docker Engine
因为 Docker 最流行使用最广泛

- 运行时 - runc
Docker 的默认 runtime

- 操作系统 - Ubuntu
选择大家熟悉的操作系统

## 安装 Docker

我们将在 ubuntu 16.04 虚拟机中安装 Docker。因为安装过程需要访问 internet, 所以虚拟机必须能够上网。

Docker 支持几乎所有的 Linux 发行版,也支持 Mac 和 Windows。各操作系统的安装方法可以访问:https://docs.docker.com/install/

Docker 分为开源免费的 CE(Community Edition)版本和收费的 EE(Enterprise Edition)版本。下面我们将按照文档,通过以下步骤在 Ubuntu 16.04 上安装 Docker CE 版本。
<!-- more -->

### 配置 Docker 的 apt 源

1. 安装包,允许 apt 命令 HTTPS 访问 Docker 源。

``` bash
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common
```
2. 添加 Docker 官方的 GPG

``` bash
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

3. 将 Docker 的源添加到 /etc/apt/sources.list

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

### 安装 Docker

``` bash
$ sudo apt-get update
$ sudo apt-get install docker-ce
```

## 运行第一个容器

环境就绪,马上运行第一个容器,执行命令:

``` bash
$ sudo docker run -d -p 80:80 httpd
```

其过程可以简单的描述为:

- 从 Docker Hub 下载 httpd 镜像。镜像中已经安装好了 Apache HTTP Server
- 启动 httpd 容器,并将容器的 80 端口映射到 host 的 80 端口

下面我们可以通过浏览器验证容器是否正常工作。在浏览器中输入 http://[your ubuntu host IP]

![成功访问](/imgs/201806/httd_run.jpg)

可以访问容器的 http 服务了,第一个容器运行成功!我们轻轻松松就拥有了一个 WEB 服务器。随着学习的深入,会看到容器技术带给我们更多的价值。

## 镜像下载加速

由于 Docker Hub 的服务器在国外,下载镜像会比较慢。我们可以去阿里巴巴或 DaoCloud 申请一个国内镜像地址。

![阿里镜像下载加速](/imgs/201806/ali_registry_mirrors.jpg)

配置镜像下载加速并重启docker服务:

``` bash
$ sudo mkdir -p /etc/docker
$ sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxl8pb5.mirror.aliyuncs.com"]
}
EOF
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```

142 changes: 142 additions & 0 deletions 2.Docker-Images.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
---
title: Docker 镜像
date: 2018-06-11 14:20:40
tags: [docker, container, image]
---
## 最小镜像

镜像是 Docker 容器的基石,容器是镜像的实例,有了镜像才能启动容器。

镜像到底包含什么呢?容器为什么是轻量级的虚拟化呢?

![运行hello world](/imgs/201806/run_hello_world.png)

首先从一个最小的镜像hello-world讲起,hello-world镜像仅有1.85kB,根据经验它肯定是不包括Linux的内核的,因为现在Linux内核大小至少100MB以上。

这么小的镜像,它能运行,是一个完整的镜像,他是怎么构建出来的呢?

![hello world dockerfile](/imgs/201806/dockerfile_hello_world.png)

这个镜像的构建文件仅有三行,第一行从空白镜像开始构建,第二行拷贝二进制hello程序,第三行运行hello程序。

/hello 就是文件系统的全部内容,连最基本的 /bin,/usr, /lib, /dev 都没有。
<!-- more -->

## Base镜像

hello-world 虽然是一个完整的镜像,但它并没有什么实际用途。通常来说,我们希望镜像能提供一个基本的操作系统环境,用户可以根据需要安装和配置软件。这样的镜像我们称作 base 镜像。

什么是base镜像?Base镜像指不依赖其他镜像,从scratch构建,其他镜像可以以之为基础镜像进行扩展。

能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等。

![CentOS Image](/imgs/201806/centos_image.png)

一个CentOS镜像为什么还不到200MB?

Linux 操作系统由内核空间和用户空间组成。内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉,rootfs被加载。用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。

![Linux bootfs or rootfs](/imgs/201806/linux_1.png)

不同 Linux 发行版的区别主要就是 rootfs。比如 Ubuntu 14.04 使用 upstart 管理服务,apt 管理软件包;而 CentOS 7 使用 systemd 和 yum。这些都是用户空间上的区别,Linux kernel 差别不大。

![容器共享Linux kernel](/imgs/201806/linux_2.png)

对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。

相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到 10MB。

如下,在CentOS 7宿主机上运行 Ubuntu 16.04容器,看到容器的内核和宿主机的内核相同,容器复用了宿主机的内核:

![容器共用宿主机内核](/imgs/201806/run_docker_ubuntu.png)

## 镜像的分层结构

如下图所示,镜像是分层存储:

![镜像分层](/imgs/201806/image_layer.jpg)

为什么镜像采用分层结构呢?

最大的好处就是资源共享,比如有多个镜像从同一个base镜像构建而来,宿主机上只需要有一份base镜像就可以了,多个镜像共用同一个base镜像。

多个容器共用同一个base镜像,当某个容器修改配置时,其他容器也会修改吗?

答案是不会,因为最上面的容器层是可写的,下面的其他层(镜像层)都是只读,当需要修改下层的文件时,会先复制此文件到上面的容器层,然后再修改。容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。

## 构建镜像

Docker支持两种方法构建镜像,一是手动构建,二是通过Dockerfile构建。

1. 通过Docker commit命令手动构建镜像

```bash
# docker run -ti --name ubuntu-vi ubuntu:16.04 bash
# apt-get update && apt-get install -y vim
# 开启另一终端,提交构建的镜像
# docker commit ubuntu-vi ubuntu-with-vi
```

2. 通过Dockerfile构建镜像

```bash
# 编写Dockerfile
# vi Dockerfile
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y vim
CMD ["/bin/bash"]
# 构建镜像
# docker build -t ubuntu-with-vi-dockerfile

```

Docker 并不建议用户通过这种方式构建镜像。原因如下:
1. 这是一种手工创建镜像的方式,容易出错,效率低且可重复性弱。比如要在 debian base 镜像中也加入 vi,还得重复前面的所有步骤。
2. 使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计,存在安全隐患。docker history 会显示镜像的构建历史,也就是 Dockerfile 的执行过程。手工创建镜像的方式无法获取history。

通过两种方式构建好的镜像如下:

![镜像](/imgs/201806/docker_build.png)

## Dockerfile常用指令

Dockerfile常用指令如下:

> FROM 指定基础镜像
> MAINTAINER 设置镜像维护者
> COPY 将文件从构建上下文复制到镜像
> ADD 同COPY,如果源文件是压缩文件自动解压缩
> ENV 设置环境变量
> EXPOSE 指定容器监听的端口
> VOLUME 定义匿名卷
> WORKDIR 为RUN、CMD、ENTRYPOINT等命令设置工作目录
> RUN 在容器中运行指定命令
> CMD 指定容器启动时运行的命令,可被替换
> ENTRYPOINT指定容器启动时运行的命令
> HEALTHCHECK 健康检查
我们通常使用 RUN 指令安装应用和软件包,构建镜像。如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。

## 镜像仓库

编译好的镜像只能在本地使用,如果想给其他人使用,最好是将容器上传到镜像仓库。容器仓库又分为公共仓库和私有仓库,hub.docker.com 是 Docker 公司提供的公有仓库,所有用户均可拉取公有仓库中的镜像,为了安全起见,通常公司会搭建自己的私有仓库。


## 镜像生命周期管理

如下是容器镜像的生命周期,包括镜像的构建、镜像打标签、推送到镜像仓库、从镜像仓库拉取镜像、镜像导入、导出、镜像删除等操作:

![镜像生命周期](/imgs/201806/docker_registry.png)

容器镜像常用命令小结:

> docker images 显示镜像列表
> docker history 显示镜像构建历史
> docker commit 从容器创建新镜像
> docker build 从 Dockerfile 构建镜像
> docker tag 给镜像打 tag
> docker pull 从 registry 下载镜像
> docker push 将镜像上传到 registry
> docker rmi 删除 Docker host 中的镜像
> docker search 搜索 Docker Hub 中的镜像
Loading

0 comments on commit 60501ba

Please sign in to comment.