容器級虛擬化,再也不爲每個虛擬機建立單獨的內核,而是經過在宿主機的內核上將6種資源經過內核機制(namespaces)隔離出來,每個namespace就是一個單獨的容器。
Linux領域的容器技術,就是靠內核級的6個namespaces、chroot和Cgroups共同實現的。php
隔離用戶空間,將進程與其餘進程隔離開來。html
namesapce | 系統調用參數 | 隔離內容 | 內核版本 |
---|---|---|---|
Mount | CLONE_NEWNW | 掛載點(文件系統) | 2.4.19 |
UTS | CLONE_NEWUTS | 主機名和域名 | 2.6.19 |
IPC | CLONE_NEWIPC | 信號量、消息隊列和共享內存 | 2.6.19 |
PID | CLONE_NEWPID | 進程編號 | 2.6.24 |
Network | CLONE_NEWNET | 網絡設備、網絡棧、端口等 | 2.6.29 |
User | CLONE_NEWUSER | 用戶和用戶組 | 3.8 |
最後一個是在內核的3.8版本才加入到內核中的。因此要想很好的使用容器技術,內核版本須要在3.8以後,也就是須要Centos7。node
容器化技術的隔離機制是靠namespaces實現,而容器化的資源分配靠的是在內核級經過CGroups機制實現。它會把系統級的資源分紅多個組,而後把每個組內的資源量指派分配到特定的namespace的進程上去。
cgroups,資源限制,限制進程佔用的CPU和內存:linux
CPU屬於可壓縮資源。內存屬於非可壓縮資源,絕對不容許越界。nginx
Docker三大編排工具:git
Compose是單機版。Swarm是集羣管理工具。github
以上這些可能都用不到,由於最流行的仍是下面這個。
kubernetes:簡稱K8s,Google開源的一個容器編排引擎。golang
k8s須要做爲一個單獨的主題,另外再去學習的工具,這裏只是把工具的名稱引出來。web
Docker架構以下,有3個部分組成。
docker
這裏有Client端和Server端(DOCKER_HOST),因此這是一個C/S架構的應用程序。
Docker deamon運行爲守護進程。因此運行後這臺主機就變成了守護進程服務器。
Docker daemon 監聽UNIX套接字或網絡接口。默認只監聽本地的UNIX套接字。
Images 鏡像,能夠從registries下載鏡像。全部鏡像都是隻讀的。
Containers 容器,啓動容器時是基於鏡像來啓動。
客戶端是用戶操做Docker的主要方式。docker命令使用Docker API,客戶端能夠與多個daemon進行通訊。
Docker的鏡像倉庫。
Docker Hub(https://hub.docker.com/ ),官方提供的鏡像倉庫,在國外。建議使用國內鏡像。
在Centos7上使用yum安裝docker。
CentOS官方源就有docker,注意這裏用的名稱是docker:
$ yum info docker 已加載插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.163.com 可安裝的軟件包 名稱 :docker 架構 :x86_64 時期 :2 版本 :1.13.1 發佈 :96.gitb2f74b2.el7.centos 大小 :18 M 源 :extras/7/x86_64 簡介 : Automates deployment of containerized applications 網址 :https://github.com/docker/docker 協議 : ASL 2.0 描述 : Docker is an open-source engine that automates the deployment of any : application as a lightweight, portable, self-sufficient container that will : run virtually anywhere. : : Docker containers can encapsulate any payload, and will run consistently on : and between virtually any server. The same container that a developer builds : and tests on a laptop will run at scale, in production*, on VMs, bare-metal : servers, OpenStack clusters, public instances, or combinations of the above. $
可是這個的版本過低了,因此不使用CentOS的源。
如今Docker軟件主要有兩個版本:
Docker另外還有一個開源的版本Moby,這個也是從原先的docker項目繼承過來,是社區維護的。而Docker-CE是Docoker公司維護的開源項目。
這裏添加阿里的鏡像源,這個是社區版Docker-CE:
$ wget -P /etc/yum.repos.d/ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
檢查版本信息,注意這裏用的名稱是docker-ce:
$ yum info docker-ce 已加載插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com 可安裝的軟件包 名稱 :docker-ce 架構 :x86_64 時期 :3 版本 :18.09.7 發佈 :3.el7 大小 :19 M 源 :docker-ce-stable/x86_64 簡介 : The open-source application container engine 網址 :https://www.docker.com 協議 : ASL 2.0 描述 : Docker is is a product for you 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 cloud 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. $
上面顯示的最新版本信息是18.09.7,因爲docker通常還要配合容器編排工具使用,如今最流行的就是k8s。而k8s還不必定支持最新版本,因此具體要安裝那個版本,還得確認一下版本的依賴關係。
查詢k8s對docker版本的依賴關係,能夠到Github的k8s的項目中,項目地址:
https://github.com/kubernetes/kubernetes
查詢版本的CHANGELOG,好比這個文件CHANGELOG-1.15.md。文件內容比較多,直接搜索「Docker version」:
The list of validated docker versions remains unchanged.
The current list is 1.13.1, 17.03, 17.06, 17.09, 18.06, 18.09. (#72823, #72831)
這裏就安裝一個不是最新的18.06版本。
查詢可用版本:
$ yum list docker-ce --showduplicates | expand 已加載插件:fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com 可安裝的軟件包 docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.03.2.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.03.3.ce-1.el7 docker-ce-stable docker-ce.x86_64 17.06.0.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.06.1.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.06.2.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.09.0.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.09.1.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.12.0.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 17.12.1.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 18.03.0.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 18.03.1.ce-1.el7.centos docker-ce-stable docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable docker-ce.x86_64 18.06.2.ce-3.el7 docker-ce-stable docker-ce.x86_64 18.06.3.ce-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.2-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.3-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.4-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.5-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.6-3.el7 docker-ce-stable docker-ce.x86_64 3:18.09.7-3.el7 docker-ce-stable $
expand 命令的效果只是讓輸出更加緊湊一點,把製表符換成空格。
安裝指定版本:
yum install docker-ce-18.06.0.ce-3.el7
啓動和驗證
啓動服務、開機啓動,查看版本信息:
$ systemctl start docker.service $ systemctl enable docker.service Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service. $ docker version Client: Version: 18.06.0-ce API version: 1.38 Go version: go1.10.3 Git commit: 0ffa825 Built: Wed Jul 18 19:08:18 2018 OS/Arch: linux/amd64 Experimental: false Server: Engine: Version: 18.06.0-ce API version: 1.38 (minimum version 1.12) Go version: go1.10.3 Git commit: 0ffa825 Built: Wed Jul 18 19:10:42 2018 OS/Arch: linux/amd64 Experimental: false $
這裏能分別看到Client端和Server端各自的版本。Docker是用Go語言開發的,這裏有顯示Go的版本。另外還有平臺的版本linux/amd64
,這個以後使用或下載其餘組件時,遇到有平臺相關的版本兼容性問題,能夠根據這個選擇對應的版本。
默認的鏡像倉庫在國外,最好使用在國內的官方鏡像站點。這裏列出了幾個:
阿里雲的不能直接使用,由於須要註冊,效果應該會很不錯。
docker-cn雖然是官方的,可是加速效果也不好。大概是不瞭解國情。
網易和中科大的均可以使用。
使用配置文件/etc/docker/daemon.json,若是目錄或文件沒有,就手動建立。在配置文件中添加以下內容:
{ "registry-mirrors": ["http://hub-mirror.c.163.com", "https://registry.docker-cn.com"] }
這裏的配置使用的是JSON格式。要是配置生效,須要重啓服務。
上面只是使用了一個配置項,完整的配置項信息能夠查看官方的文檔:
https://docs.docker.com/engine/reference/commandline/dockerd/#Daemon-configuration-file
應該是全部的配置項都在這裏了,以後須要的時候能夠再來查閱。
不使用任何參數執行 docker 打印的幫助信息以下:
$ docker Usage: docker [OPTIONS] COMMAND A self-sufficient runtime for containers Options: --config string Location of client config files (default "/root/.docker") -D, --debug Enable debug mode -H, --host list Daemon socket(s) to connect to -l, --log-level string Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info") --tls Use TLS; implied by --tlsverify --tlscacert string Trust certs signed only by this CA (default "/root/.docker/ca.pem") --tlscert string Path to TLS certificate file (default "/root/.docker/cert.pem") --tlskey string Path to TLS key file (default "/root/.docker/key.pem") --tlsverify Use TLS and verify the remote -v, --version Print version information and quit Management Commands: config Manage Docker configs container Manage containers image Manage images network Manage networks node Manage Swarm nodes plugin Manage plugins secret Manage Docker secrets service Manage services stack Manage Docker stacks swarm Manage Swarm system Manage Docker trust Manage trust on Docker images volume Manage volumes Commands: attach Attach local standard input, output, and error streams to a running container build Build an image from a Dockerfile commit Create a new image from a container's changes cp Copy files/folders between a container and the local filesystem create Create a new container diff Inspect changes to files or directories on a container's filesystem events Get real time events from the server exec Run a command in a running container export Export a container's filesystem as a tar archive history Show the history of an image images List images import Import the contents from a tarball to create a filesystem image info Display system-wide information inspect Return low-level information on Docker objects kill Kill one or more running containers load Load an image from a tar archive or STDIN login Log in to a Docker registry logout Log out from a Docker registry logs Fetch the logs of a container pause Pause all processes within one or more containers port List port mappings or a specific mapping for the container ps List containers pull Pull an image or a repository from a registry push Push an image or a repository to a registry rename Rename a container restart Restart one or more containers rm Remove one or more containers rmi Remove one or more images run Run a command in a new container save Save one or more images to a tar archive (streamed to STDOUT by default) search Search the Docker Hub for images start Start one or more stopped containers stats Display a live stream of container(s) resource usage statistics stop Stop one or more running containers tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE top Display the running processes of a container unpause Unpause all processes within one or more containers update Update configuration of one or more containers version Show the Docker version information wait Block until one or more containers stop, then print their exit codes Run 'docker COMMAND --help' for more information on a command. $
這裏有 Management Commands 和 Commands。docker有不少子命令,早期的docker是Commands風格的,每個子命令都是單獨的。如今命令多了,爲這些子命令分了不少組進行管理,這個就是Management Commands。因此兩種命令風格效果是同樣的。好比,下面兩個命令是同樣的:
docker run docker container run
建議儘可能使用 Management Commands 的命令。
Go 命令的調用流程
這裏是題外話,這麼好的命令行界面,好奇是具體怎麼作的。
使用了golang命令行庫cobra:https://github.com/spf13/cobra。
具體能夠看下這篇文章的分析:https://www.jianshu.com/p/9900ec52f2c1
有一點可能須要注意,Docker的設計是Client-Server模式的,平時咱們用的docker這個命令被分散到 https://github.com/docker/cli 這個倉庫去了。
以前使用docker version
命令,查看了版本信息,這個使用docker info
命令能夠查看更詳細的信息:
$ docker system info Containers: 0 // 總的容器數量 Running: 0 // 運行狀態的容器數量 Paused: 0 // 暫停狀態的容器數量 Stopped: 0 // 中止狀態的容器數量 Images: 0 // 鏡像的數量 Server Version: 18.06.0-ce // 服務器版本 Storage Driver: overlay2 // 存儲驅動後端 Backing Filesystem: xfs Supports d_type: true Native Overlay Diff: true Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: // 插件 Volume: local Network: bridge host macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog Swarm: inactive Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: d64c661f1d51c48782c9cec8fda7604785f93587 runc version: 69663f0bd4b60df09991c08812a60108003fa340 init version: fec3683 Security Options: // 安全選項 seccomp Profile: default Kernel Version: 3.10.0-957.el7.x86_64 // 內核版本 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 1 Total Memory: 908.2MiB Name: Docker ID: HB7V:B35V:AGQR:Z4JM:WLZ3:T53Y:DXAD:R3HE:OIMS:ODXL:QKDB:MQES Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Registry Mirrors: // 鏡像加速器 http://hub-mirror.c.163.com/ https://registry.docker-cn.com/ Live Restore Enabled: false $
以上部分信息,我用相似註釋的方式在對應的行里加了說明。
查看容器可使用的網絡:
$ docker network ls NETWORK ID NAME DRIVER SCOPE 39cd19b7d266 bridge bridge local d086953087bb host host local fa0c7f1fb6ca none null local $
容器網絡的內容也是須要單獨展開的,這裏只是演示一下網絡命令。
可使用命令來搜索鏡像:docker search
。這個命令不屬於任何一個Management Commands,因此就直接這麼用:
$ docker search nginx
命令的輸出結果貼出來不是很好看,下面是利用--format參數,輸出完整的JSON格式的內容:
$ docker search nginx --limit 5 --format '{{json .}}' {"Description":"Official build of Nginx.","IsAutomated":"false","IsOfficial":"true","Name":"nginx","StarCount":"11680"} {"Description":"Automated Nginx reverse proxy for docker con…","IsAutomated":"true","IsOfficial":"false","Name":"jwilder/nginx-proxy","StarCount":"1627"} {"Description":"Container running Nginx + PHP-FPM capable of…","IsAutomated":"true","IsOfficial":"false","Name":"richarvey/nginx-php-fpm","StarCount":"726"} {"Description":"Bitnami nginx Docker Image","IsAutomated":"true","IsOfficial":"false","Name":"bitnami/nginx","StarCount":"69"} {"Description":"NGINX Ingress Controller for Kubernetes","IsAutomated":"false","IsOfficial":"false","Name":"nginx/nginx-ingress","StarCount":"20"}
這裏不但獲取了全部的字段的內容,還有每一個字段的字段名。
如今還能夠調整--format參數,自定義輸出的格式:
$ docker search nginx --limit 5 --format '{{.Name}}\t{{.Description}}\t{{.StarCount}}\t{{.IsOfficial | printf "%q"}}\t{{.IsAutomated | printf "%q"}}' nginx Official build of Nginx. 11680 "[OK]" "" jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1627 "" "[OK]" richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 726 "" "[OK]" bitnami/nginx Bitnami nginx Docker Image 69 "" "[OK]" nginx/nginx-ingress NGINX Ingress Controller for Kubernetes 20 "" "" $
默認輸出的內容若是太長,會被階段,好比Description字段。這時可使用--no-trunc參數,阻止內容被截斷。
不過搜索的結構沒有詳細的tag信息,因此這個命令沒太大用處。要搜索鏡像就直接上 hub.docker.com 查。
Docker Hub 搜索鏡像
使用瀏覽器訪問docker hub: https://hub.docker.com/
在首頁搜索框內輸入要搜索的鏡像名稱,好比「hello-world」。進入後,點擊TAGS標籤,能夠查看這個鏡像的不一樣的版本。
其餘鏡像倉庫
除了Docker Hub官方的鏡像倉庫之外,還有其餘鏡像倉庫,好比Quay:https://quay.io/
首先要在本地建立鏡像,能夠去鏡像倉庫獲取。
把鏡像從鏡像倉庫拖(pull)下來:
$ docker image pull hello-world Using default tag: latest latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:6540fc08ee6e6b7b63468dc3317e3303aae178cb8a45ed3123180328bcc1d20f Status: Downloaded newer image for hello-world:latest $
若是不指定tag,默認就是latest。
查看就是ls:
$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289e99eb9 6 months ago 1.84kB $
這裏的 IMAGE ID 是鏡像的惟一標識。指定鏡像的時候可使用 REPOSITORY 和 TAG,不過本地鏡像能夠沒有這兩個屬性。可是必定會有 IMAGE ID,經過 IMAGE ID 也能夠指明鏡像。
上面顯示的ID只是一部分,可使用--no-trunc參數查看完整的:
$ docker image ls --no-trunc --format '{{.Repository}}:{{.Tag}} {{.ID}}' hello-world:latest sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e $
在指明鏡像的時候,使用完整的或者部分ID都是能夠的。
若是下錯了,或者不用了,也能夠刪除。命令是docker image rm
,或者也能夠用docker rmi
。
注意,這裏不是docker rm
,這個命令操做的容器,對應的命令是docker container rm
。
這也是建議使用 Management Commands 命令的緣由,明確指定要作哪一類的操做。這樣在須要操做 image 的時候不會由於誤操做而對 container 執行了命令。
先看下一幫助命令,下面是全部容器相關的子命令:
$ docker container --help Usage: docker container COMMAND Manage containers Commands: attach Attach local standard input, output, and error streams to a running container commit Create a new image from a container's changes cp Copy files/folders between a container and the local filesystem create Create a new container diff Inspect changes to files or directories on a container's filesystem exec Run a command in a running container export Export a container's filesystem as a tar archive inspect Display detailed information on one or more containers kill Kill one or more running containers logs Fetch the logs of a container ls List containers pause Pause all processes within one or more containers port List port mappings or a specific mapping for the container prune Remove all stopped containers rename Rename a container restart Restart one or more containers rm Remove one or more containers run Run a command in a new container start Start one or more stopped containers stats Display a live stream of container(s) resource usage statistics stop Stop one or more running containers top Display the running processes of a container unpause Unpause all processes within one or more containers update Update configuration of one or more containers wait Block until one or more containers stop, then print their exit codes Run 'docker container COMMAND --help' for more information on a command. $
主要命令說明:
執行 docker container run --help
查看命令運行的格式:
docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]
啓動容器時執行的命令
[COMMAND] 是可選的,指定啓動容器時運行的命令。
[ARG...] 是像命令傳遞的參數。
Docker的容器是爲了運行單個程序的。就是單個進程,不過容器內部也是能夠同時運行多個進程的。
每一個鏡像都有定義默認要運行的程序。基於一個鏡像啓動容器的時,若是沒有指定命令,就執行鏡像默認指定的程序。
固然也能夠手動指定鏡像啓動時運行的命令,就是上面的[COMMAND]參數。
啓動容器時的選項
[OPTIONS] 是一大堆run命令的參數。下面挑幾個重要的說:
這裏來實際的運行個容器,並進行各類操做。
busybox的鏡像很是小,它並非一個系統發行版。最初這個工具是爲了在一張軟盤上建立一個可引導的 GNU/Linux 系統,這能夠用做安裝盤和急救盤。它是一個集成了三百多個最經常使用Linux命令和工具的軟件。
直接啓動
直接將鏡像啓動爲容器:
$ docker container run --name bx0 busybox $ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES $
此時ls也看不到這個容器,不過容器並無被刪除而只是出於中止狀態。默認只顯示運行狀態的容器,這裏須要加上-a參數:
$ docker container ls -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3a9b8eb31e01 busybox "sh" 7 minutes ago Exited (0) 7 minutes ago bx0 $
這裏注意一下 COMMAND 字段的值,這個是容器啓動時運行的命令。啓動容器的時候沒有指定,這裏就是默認的命令。
此次啓動容器顯然是有問題的,先把這個容器刪除了,而後繼續往下看:
$ docker container rm bx0
啓動並開啓終端
此次啓動時加上 -it 參數,分配一個 shell 終端:,
$ docker run --name bx1 -it busybox / # ls bin dev etc home proc root sys tmp usr var / # ls bin
最後的一條命令 ls bin
能夠看到不少命令。這些命令就是 busybox 支持的命令。
如今是一個 shell 的交互式接口,能夠直接運行命令,先看下 ps 命令:
/ # ps PID USER TIME COMMAND 1 root 0:00 sh 10 root 0:00 ps / #
能夠看到 sh 命令的 PID 是1。PID爲1的進程是init
Docker 容器啓動時,默認會把容器內部第一個進程,也就是pid=1的程序,做爲docker容器是否正在運行的依據,若是 docker 容器pid=1的進程掛了,那麼docker容器便會直接退出。
此時若是退出shell,那麼這個容器也就關閉了。第一次啓動容器時,沒有開啓終端,其實就是啓動了一個 sh 命令,而後就退出終端了。因此啓動後容器就是中止狀態的。
/ # exit $ docker container ls -a --format '{{.Names}}: {{.Status}}' bx1: Exited (126) 4 minutes ago $
再次啓動容器
容器已經建立好了,此次直接 start 就能夠了:
$ docker container start bx1 bx1 $ docker container ls -a --format '{{.Names}}: {{.Status}}' bx1: Up 2 seconds $
可是如今並無進入到終端。
用 attach 命令就能夠再次進入終端:
$ docker container attach bx1 / # ps PID USER TIME COMMAND 1 root 0:00 sh 6 root 0:00 ps / #
還能夠在 start 的時候直接加上 -ai 參數,效果也是同樣的:
/ # exit $ docker container start bx1 -ai / #
exec 命令
最後還有一種方法,不用進入宿主機,直接在宿主機上對容器發送命令,並在宿主機上獲得命令的結果:
$ docker container start bx1 bx1 $ docker container exec bx1 ps PID USER TIME COMMAND 1 root 0:00 sh 6 root 0:00 ps $
這裏有張圖,描述了容器的各個經常使用命令和容器狀態的轉換:
圖裏有個OOM(Out Of Memory)內存不足,是內存使用過多。OOM狀態的容器會被kill掉,來保證系統的可持續運行。OOM被kill以後就看容器的機制,是否會自動重啓,不然就進入stopped狀態。