-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,637 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 中的镜像 |
Oops, something went wrong.