打算自學DockerOpenStackELKPython等知識,此處先研究Docker。文末有總結(summary),可直接前往查看。

2016.07.21更新: 公司準備上Docker,由我負責做分享、討論,重新寫了一份文檔,對Docker進行了簡單的介紹,文檔已經上傳至 Google Drive

Docker Introduction

What is Docker

Docker是一款開源的,提供Operating-system-level virtualization(操作系統級別的虛擬化的)容器(container)產品。利用Linux Kernel中的control groupsnamespacesadvanced multi layered unification filesystem等特性,實現在單個Linux實例上運行多個獨立的容器(container),減少了啓動和維護virtual machine的開銷。 — Docker (software)

此處插一句 Debian的聯合創建者同時也是Docker的開發者之一 Ian Murdock,於2015年12月28日去世。此爲Docker官方博客發佈的文章In Memoriam: Ian Murdocklempstacker在此緬懷一下逝者,歷史會銘記其爲開源世界作出的卓越貢獻。

好,言歸正傳,官方稱 >Docker allows you to package an application with all of its dependencies into a standardized unit for software development.

可以說這就是Docker的特性。

Differences

Docker Container本質上也是虛擬化,只不過與virtual machine(如Vagrant)的實現方式不同。下圖介紹了二者的區別,圖片來自What is Docker?

Virtual Machines

Each virtual machine includes the application, the necessary binaries and libraries and an entire guest operating system - all of which may be tens of GBs in size.

每個虛擬機包含了應用程序、需要的二進制和庫文件,以及整個guest操作系統,整個需要數十GB的空間。

Virtual Machines

Containers

Containers include the application and all of its dependencies, but share the kernel with other containers. They run as an isolated process in userspace on the host operating system. They’re also not tied to any specific infrastructure – Docker containers run on any computer, on any infrastructure and in any cloud.

容器包含應用程序及其所有的依賴文件,但與其它容器共享內核(kernel),它們在宿主機(host)操作系統的用戶空間(userspace)中以獨立的進程(process)運行。它們不與任何具體的基礎架構(infrastructure)關聯。Docker容器運行在任意計算機、任意基礎架構和任意一種雲環境中。

Containers

簡言之,Virtual Machine虛擬的是整個操作系統,而Container是在Linux kernel的基礎上實現獨立的運行環境。

Architecture

Docker uses a client-server architecture. The Docker client talks to the Docker daemon, which does the heavy lifting of building, running, and distributing your Docker containers. Both the Docker client and the daemon can run on the same system, or you can connect a Docker client to a remote Docker daemon. The Docker client and daemon communicate via sockets or through a RESTful API. — Understand the architecture

architecture

關於Docker的具體架構介紹,請移步 Understand the architecture

Official Site

以下是Docker相關官方站點

Site Website
Official Site https://www.docker.com/
GitHub https://github.com/docker
Documentation https://docs.docker.com/
Tech Blog https://blog.docker.com/category/engineering/
Blog https://blog.docker.com/
Twitter https://twitter.com/docker
Youtube https://www.youtube.com/user/dockerrun

How to Learning

Docker的github中有一篇docker for beginers的tutorial,可作爲Docker啓蒙讀物。

不過lempstacker打算直接通過其官方文檔學習Docker的使用。Docker官網雖提供了Get Started with Docker Engine for Linux,但是apt環境。而本人使用的是CentOS 7,故從 CentOS開始。

Installation on CentOS 7

Docker runs on CentOS 7.X. An installation on other binary compatible EL7 distributions such as Scientific Linux might succeed, but Docker does not test or support Docker on these distributions.

Docker可運行在CentOS 7.X環境中,不過EL7的其它衍生版如Scientific Linux則無法保證是否成功,Docker官方未支持這些發行版也沒做過測試。

Prerequisites

Docker成功運行須2個條件 * 64-bit操作系統 (CentOS 7默認是64位) * kernel(內核)版本至少3.10 (CentOS 7.2.1511內核版本是3.10.0-327)

還有一個建議 * 更新系統,確保修復了潛在的Kernel bugs

關於CentOS 7.2.1511安裝包信息,可參閱本人Blog Use Script To Formatting And List Info Of RPM Packages Installed In CentOS

[flying@lemp ~]$ uname -r
3.10.0-327.10.1.el7.x86_64
[flying@lemp ~]$

簡言之CentOS 7.2.1511支持運行Docker

Installation

有2種安裝方式 * 通過Docker官方倉庫使用yum安裝 * 通過curl -fsSL https://get.docker.com/ | sh安裝,仍通過yum包管理器

二者本質是一樣的

  • Install with yum ``` #更新系統 sudo yum update

#添加docker倉庫 sudo tee /etc/yum.repos.d/docker.repo <<-‘EOF’ [dockerrepo] name=Docker Repository baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/ enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg EOF

#安裝Docker sudo yum install docker-engine

#啓動Docker服務 sudo service docker start

#通過容器中的測試鏡像(hello-world)驗證Docker是否安裝正確 sudo docker run hello-world


* Install with the script

#更新系統 sudo yum update

#運行腳本(添加倉庫,安裝docker) $ curl -fsSL https://get.docker.com/ | sh

#啓動Docker服務 sudo service docker start

#通過容器中的測試鏡像(hello-world)驗證Docker是否安裝正確 sudo docker run hello-world



此處本人使用第一種方案,以下是安裝後的測試過程

#查看docker安裝包 [flying@lemp ~]$ rpm -qa | grep docker docker-engine-1.10.3-1.el7.centos.x86_64 docker-engine-selinux-1.10.3-1.el7.centos.noarch

#查看倉庫文件 [flying@lemp ~]$ cat /etc/yum.repos.d/docker.repo [dockerrepo] name=Docker Repository baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/ enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg

#查看版本 [flying@lemp ~]$ docker -v Docker version 1.10.3, build 20f81dd

#啓動Docker服務 [flying@lemp ~]$ sudo systemctl start docker

#查看Docker服務狀態 [flying@lemp ~]$ systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled) Active: active (running) since Mon 2016-04-04 10:12:32 CST; 4s ago Docs: https://docs.docker.com Main PID: 23987 (docker) CGroup: /system.slice/docker.service └─23987 /usr/bin/docker daemon -H fd://

#測試命令 [flying@lemp ~]$ docker run hello-world docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?. See ‘docker run –help’.

#使用sudo再次測試 [flying@lemp ~]$ sudo docker run hello-world Unable to find image ‘hello-world:latest’ locally latest: Pulling from library/hello-world 03f4658f8b78: Pull complete a3ed95caeb02: Pull complete Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7 Status: Downloaded newer image for hello-world:latest

Hello from Docker. This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the “hello-world” image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.

To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account: https://hub.docker.com

For more examples and ideas, visit: https://docs.docker.com/userguide/

[flying@lemp ~]$


#### Docker Info

#查看配置文件 [flying@lemp ~]$ rpm -qc docker-engine

#查看安裝信息 [flying@lemp ~]$ rpm -qi docker-engine Name : docker-engine Version : 1.10.3 Release : 1.el7.centos Architecture: x86_64 Install Date: Mon 04 Apr 2016 10:06:53 AM CST Group : Tools/Docker Size : 42886943 License : ASL 2.0 Signature : RSA/SHA512, Fri 11 Mar 2016 05:37:10 AM CST, Key ID f76221572c52609d Source RPM : docker-engine-1.10.3-1.el7.centos.src.rpm Build Date : Thu 10 Mar 2016 11:40:47 PM CST Build Host : 0bc4c5093a7b Relocations : (not relocatable) Packager : Docker support@docker.com Vendor : Docker URL : https://dockerproject.org Summary : The open-source application container engine Description : Docker is an open source project to build, ship and run any application as a lightweight container.

Docker containers are both hardware-agnostic and platform-agnostic. This means they can run anywhere, from your laptop to the largest EC2 compute instance and everything in between - and they don’t require you to use a particular language, framework or packaging system. That makes them great building blocks for deploying and scaling web apps, databases, and backend services without depending on a particular stack or provider.

#列出安裝包中的文件 [flying@lemp ~]$ rpm -ql docker-engine /etc/udev/rules.d/80-docker.rules /usr/bin/docker /usr/lib/systemd/system/docker.service /usr/lib/systemd/system/docker.socket /usr/libexec/docker/dockerinit /usr/share/bash-completion/completions/docker /usr/share/doc/docker-engine-1.10.3 /usr/share/doc/docker-engine-1.10.3/AUTHORS /usr/share/doc/docker-engine-1.10.3/CHANGELOG.md /usr/share/doc/docker-engine-1.10.3/CONTRIBUTING.md /usr/share/doc/docker-engine-1.10.3/LICENSE /usr/share/doc/docker-engine-1.10.3/MAINTAINERS /usr/share/doc/docker-engine-1.10.3/NOTICE /usr/share/doc/docker-engine-1.10.3/README.md /usr/share/fish/vendor_completions.d/docker.fish /usr/share/man/man1/docker-attach.1.gz /usr/share/man/man1/docker-build.1.gz /usr/share/man/man1/docker-commit.1.gz /usr/share/man/man1/docker-cp.1.gz /usr/share/man/man1/docker-create.1.gz /usr/share/man/man1/docker-diff.1.gz /usr/share/man/man1/docker-events.1.gz /usr/share/man/man1/docker-exec.1.gz /usr/share/man/man1/docker-export.1.gz /usr/share/man/man1/docker-history.1.gz /usr/share/man/man1/docker-images.1.gz /usr/share/man/man1/docker-import.1.gz /usr/share/man/man1/docker-info.1.gz /usr/share/man/man1/docker-inspect.1.gz /usr/share/man/man1/docker-kill.1.gz /usr/share/man/man1/docker-load.1.gz /usr/share/man/man1/docker-login.1.gz /usr/share/man/man1/docker-logout.1.gz /usr/share/man/man1/docker-logs.1.gz /usr/share/man/man1/docker-network-connect.1.gz /usr/share/man/man1/docker-network-create.1.gz /usr/share/man/man1/docker-network-disconnect.1.gz /usr/share/man/man1/docker-network-inspect.1.gz /usr/share/man/man1/docker-network-ls.1.gz /usr/share/man/man1/docker-network-rm.1.gz /usr/share/man/man1/docker-pause.1.gz /usr/share/man/man1/docker-port.1.gz /usr/share/man/man1/docker-ps.1.gz /usr/share/man/man1/docker-pull.1.gz /usr/share/man/man1/docker-push.1.gz /usr/share/man/man1/docker-rename.1.gz /usr/share/man/man1/docker-restart.1.gz /usr/share/man/man1/docker-rm.1.gz /usr/share/man/man1/docker-rmi.1.gz /usr/share/man/man1/docker-run.1.gz /usr/share/man/man1/docker-save.1.gz /usr/share/man/man1/docker-search.1.gz /usr/share/man/man1/docker-start.1.gz /usr/share/man/man1/docker-stats.1.gz /usr/share/man/man1/docker-stop.1.gz /usr/share/man/man1/docker-tag.1.gz /usr/share/man/man1/docker-top.1.gz /usr/share/man/man1/docker-unpause.1.gz /usr/share/man/man1/docker-update.1.gz /usr/share/man/man1/docker-version.1.gz /usr/share/man/man1/docker-volume-create.1.gz /usr/share/man/man1/docker-volume-inspect.1.gz /usr/share/man/man1/docker-volume-ls.1.gz /usr/share/man/man1/docker-volume-rm.1.gz /usr/share/man/man1/docker-wait.1.gz /usr/share/man/man1/docker.1.gz /usr/share/man/man5/Dockerfile.5.gz /usr/share/man/man5/config-json.5.gz /usr/share/nano/Dockerfile.nanorc /usr/share/vim/vimfiles/doc/dockerfile.txt /usr/share/vim/vimfiles/ftdetect/dockerfile.vim /usr/share/vim/vimfiles/syntax/dockerfile.vim /usr/share/zsh/vendor-completions/_docker [flying@lemp ~]$


### Docker group
以下英文來自官方文檔 [Create a docker group](https://docs.docker.com/engine/installation/linux/centos/#create-a-docker-group)

>The `docker` daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user `root` and other users can access it with `sudo`. For this reason, `docker` daemon always runs as the `root` user.

(出於系統安全考慮),`docker daemon`(守護進程)綁定`Unix socket`而非`TCP port`,默認情況下,`Unix socket`的所有着是`root`和其它擁有`sudo`權限的用戶。故而,`docker daemon`須以`root`用戶運行。


>To avoid having to use `sudo` when you use the `docker` command, create a Unix group called `docker` and add users to it. When the `docker` daemon starts, it makes the ownership of the Unix socket read/writable by the `docker` group.

爲避免使用`docker`命令時使用`sudo`,創建名爲`docker`的用戶組,將使用的用戶添加到該組。當`docker daemon`(守護進程)啓動時,確保`Unix socket`的讀寫權限歸`docker`用戶組所有。

>**Warning**: The `docker` group is equivalent to the `root` user; For details on how this impacts security in your system, see [Docker Daemon Attack Surface](https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface) for details.

**提醒**: `docker`用戶組等效於`root`用戶,該操作如何影響系統安全,詳見[Docker Daemon Attack Surface](https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface)。

>Docker Daemon Attack Surface
* only trusted users should be allowed to control your Docker daemon
* recommended to run exclusively Docker in the server, and move all other services within containers controlled by Docker.


官方提供的操作過程
* `sudo usermod -aG docker your_username`
    * 也可使用命令`sudo gpasswd -a <user> docker`將用戶添加入用戶組`docker`,來自書籍 `Docker Cookbook` page2
* Log out and log back in.(This ensures your user is running with the correct permissions.)
* `docker run hello-world` (Verify your work by running docker without sudo)

使用命令`sudo usermod -aG docker your_username`將用戶名添加到用戶組`docker`中,如果用戶組`docker`不存在會自動創建。

#### Add user into group

#添加用戶進入用戶組docker [flying@lemp ~]$ sudo usermod -aG docker flying

#查看用戶組文件 [flying@lemp ~]$ sudo tail -1 /etc/gshadow docker:!::flying

#查看用戶 [flying@lemp ~]$ id flying uid=1000(flying) gid=1000(flying) groups=1000(flying),975(docker) [flying@lemp ~]$


#### Relogin and Run docker without sudo
退出系統,重新登錄後執行`docker run hello-world`

[flying@lemp ~]$ docker run hello-world

Hello from Docker. This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the “hello-world” image from the Docker Hub. 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.

To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account: https://hub.docker.com

For more examples and ideas, visit: https://docs.docker.com/userguide/

[flying@lemp ~]$

可以看到,現在可直接使用`docker`命令


## Systemd Configuration
`Docker`官方提供了`systemd`配置文檔 [Control and configure Docker with systemd](https://docs.docker.com/engine/admin/systemd/),可對配置文件進行自定義操作。

在[docker github repository](https://github.com/docker/docker/tree/master/contrib/init/systemd)也提供了示例文件。

通過命令`rpm -qc docker-engine`未查找到`docker`有配置文件。

通過命令`rpm -ql docker-engine`查找到如下信息

[flying@lemp ~]$ rpm -ql docker-engine /etc/udev/rules.d/80-docker.rules /usr/bin/docker /usr/lib/systemd/system/docker.service /usr/lib/systemd/system/docker.socket /usr/libexec/docker/dockerinit /usr/share/bash-completion/completions/docker …. [flying@lemp ~]$


在目錄`/usr/lib/systemd/system/`下有文件`docker.service`和`docker.socket`


* docker.socket

[flying@lemp ~]$ cat /usr/lib/systemd/system/docker.socket [Unit] Description=Docker Socket for the API PartOf=docker.service

[Socket] ListenStream=/var/run/docker.sock SocketMode=0660 SocketUser=root SocketGroup=docker

[Install] WantedBy=sockets.target


* docker.service

[flying@lemp ~]$ cat /usr/lib/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=https://docs.docker.com After=network.target docker.socket Requires=docker.socket

[Service] Type=notify ExecStart=/usr/bin/docker daemon -H fd:// MountFlags=slave LimitNOFILE=1048576 LimitNPROC=1048576 LimitCORE=infinity TimeoutStartSec=0

[Install] WantedBy=multi-user.target [flying@lemp ~]$ ```

Control Docker daemon

可使用如下命令控制docker服務

type command
Status sudo systemctl status docker
Start sudo systemctl start docker
Stop sudo systemctl stop docker
Enable sudo systemctl enable docker
Disable sudo systemctl disable docker

Uninstallation

卸載步驟 * 查看已安裝的docker軟件包 * rpm -qa | grep docker * yum list installed | grep docker * 使用yum命令卸載 * sudo yum remove docker* * 移除目錄/var/lib/docker * sudo rm -rf /var/lib/docker * 移除用戶自己創建的相關配置文件 * 移除docker.repo * sudo rm -rf /etc/yum.repos.d/docker.repo

Summary

  • Docker是基於Linux Kernel的容器,無需虛擬整個操作系統;
  • 在CentOS平臺,Docker只支持CentOS 7.X (可直接運行在CentOS 7.2.1511中)
    • 須是64位操作系統
    • Linux內核版本至少3.10
  • 安裝可通過yum或執行腳本,二者本質一直
  • docker daemon(守護進程)綁定Unix socket(套接字,默認所有者是root),故須使用root權限執行docker命令
    • 爲避免執行docker命令時須輸入sudo,可將用戶加入用戶組docker
    • 執行命令sudo usermod -aG docker your_username
    • 因執行docker時具有root權限,須注意系統安裝,詳見Docker Daemon Attack Surface
  • 可使用system管理docker服務

Change Log

  • 2016.04.04 11:30 Thu Asia/Beijing
    • 初稿完成
  • 2016.07.21 15:25 Thu Asia/Shanghai
    • 更新,添加文檔共享鏈接

  • Note Time: 2016.04.04 11:30 Thu
  • Note Location: Asia/Beijing
  • Writer: lempstacker