Docker容器從入門到入門

1、概述

一、容器爲解決什麼問題

如今的軟件系統已經很是複雜。一方面包含多種服務,這些服務有本身所依賴的庫和軟件包;另外一方面存在多種部署環境。這就產生了一個問題:如何讓每種服務可以在全部的部署環境中順利運行?git

容器的設計理念由碼頭上的集裝箱而來,經過集裝箱的標準化相互隔離實現軟件系統依賴的打包與運行隔離。redis

二、Docker是什麼

Docker如今幾乎是容器的代名詞,它同時也是Docker公司的名字。不過咱們一般所說的Docker指的是容器或者容器技術docker

使用Docker以前,須要安裝它。以CentOS爲例:shell

# yum install docker-ce
# systemctl start docker
複製代碼

以後即可以使用docker命令操做容器或鏡像了(容器與鏡像下文會講到)。centos

三、容器優勢

  • 一致的運行環境:Docker的鏡像提供了除內核外完整的運行時環境,確保了應用運行環境一致性;
  • 極其輕量:只打包了必要的Bin/Lib,容器不是模擬一個完整的操做系統,而是對進程進行隔離,是進程級別的
  • 秒級部署:根據鏡像的不一樣,容器的部署大概在毫秒與秒之間(比虛擬機強不少);
  • 易於移植:一次構建,隨處部署;
  • 彈性伸縮:Kubernetes、Swam、Mesos這類開源、方便、好使的容器管理平臺有着很是強大的彈性管理能力。

四、容器的主要應用場景

  • 持續集成和持續部署(CI/CD): 經過Docker完成持續集成管道自動化和應用部署;
  • 微服務

2、Docker中的概念及使用

一、鏡像(Image)

Docker鏡像是Docker容器運行的基礎,沒有Docker鏡像,就沒有Docker容器。鏡像與容器就像是面向對象程序設計中的實例同樣,鏡像是靜態的定義,容器是鏡像運行時的實體數組

鏡像是一個特殊的文件系統,除了提供容器運行時所需的程序資源配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。 鏡像不包含任何動態數據,其內容在構建以後也不會被改變安全

(1) 鏡像的獲取方式一般有3種:

  1. 經過Dockerhub提供;
  2. 經過某一個已經運行的容器生成鏡像(下文講);
  3. 使用Dockerfile生成(下文講);

上面是使用pull子命令從DockerHub下載centos:latest鏡像,其中centos是鏡像名,latest是標籤名。使用docker images命令已經能夠看到剛下載的centos鏡像了。bash

(2) 鏡像經常使用操做

從倉庫拉取鏡像: # docker pull <image_id> 有時候可能須要先登陸docker login <registry_host>服務器

從容器生成鏡像: # docker commit <container_id> <image_name>網絡

刪除鏡像: # docker rmi [-f] <image_id | image_name>

轉移鏡像: # docker save <image_id | image_name> a_file_name.tar 保存鏡像到文件 # docker load a_file_name.tar 加載鏡像文件到本地鏡像庫

二、容器(Container)

容器是鏡像運行時的實體。容器能夠被建立、啓動、中止、刪除、暫停等。 容器的實質是進程,但與直接在宿主執行的進程不一樣,容器進程運行於屬於本身的獨立的命名空間。

(1) 啓動容器

Docker啓動容器的命令格式:Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...],如今使用咱們下載的centos鏡像啓動一個容器:

上圖使用run命令啓動一個容器(注意容器啓動先後的whoami輸出以及終端提示符的變化)。

  • -ti 會進入容器的終端(使用ctrl-p+ctrl-q方式返回宿主機);
  • -name test 容器名以test命令,不指定會隨機去一個字符串;
  • centos:latest 啓動容器使用的鏡像名;
  • /bin/bash 容器啓動後的執行命令;

除了這裏的幾個啓動參數外,啓動容器還常用如下OPTIONS

  • --privileged=true 進入容器後,使用真正的root權限;
  • --net host 表示在容器內與主機共享網卡,host是安裝Docker時在主機上建立的三個網絡之一;
  • --volume host_dir:container_dir 把容器內的container_dir掛載到宿主機的host_dir目錄;
  • --env 環境變量名=value 設置容器內的環境變量;
  • --cpu-shares n 設置容器佔用CPU的權重n,這個權重是相對的,第一個容器是10,第二個是20,那第二個容器佔用的CPU就是第一個的2倍;
  • -p host_port:container_port/udp 宿主機與容器的端口映射,默認是tcp,若是是udp須要/udp

(2) 容器基本操做

啓動容器# docker run [OPTIONS] <image_name | image_id> [COMMAND] [ARG...]

查看容器信息: 使用inspect子命令查看容器/鏡像的元數據。包括id啓動命令網絡鏈接方式端口映射等信息。

進入容器# docker exec -it <container_name | container_id>

中止容器# docker stop/kill <container_name | container_id>

刪除容器# docker rm [-f] <container_name | container_id>

三、Dockerfile

雖然DockerHub提供了衆多Linux鏡像,但若是須要定製,DockerHub仍是不能知足的。這個時候就須要基於DockerHub提供的鏡像作一些擴展。

Dockerfile

(1) 經常使用關鍵字

  • FROM 使用一個基礎鏡像構建;
  • RUN 執行一個shell命令,一般用來安裝工具;
  • ENV 設置容器內的環境變量;
  • COPY 拷貝宿主機文件到鏡像內;
  • ADD 拷貝宿主機文件到鏡像內,並解壓;
  • WORKDIR 設置容器啓動時的工做目錄,默認會cd到該目錄,若是目錄不存在會自動建立;

(2) 兩個特殊的關鍵字

1. CMD

CMD指令容許用戶指定容器啓動的默認執行的命令。此命令會在容器啓動且docker run沒有指定其餘命令時運行。

  • 若是docker run指定了其餘啓動命令,CMD指定的默認命令將被忽略;不然默認執行CMD指定的命令;
  • 若是Dockerfile中有多個CMD指令,只有最後一個CMD有效;

CMD的三種格式(不僅是CMD可使用,RUNENTRYPOINT也可使用這三種方式):

  1. /bin/bash -c的方法執行命令。好比CMD /bin/bash -c "echo hello world"
  2. 運行一個可執行文件並提供參數,稱爲Shell方式。好比CMD echo "hello world"
  3. 可執行文件連同參數經過一個數組提供,成爲Exec方式,好比CMD ["echo", "hello world"]

1. ENTRYPOINT ENTRYPOINTCMD相似,都是指定容器的啓動參數。不一樣之處在於:

  • ENTRYPOINT必定會執行,不會被忽略;
  • CMD指令容許用戶指定容器啓動的默認執行的命令。此命令會在容器啓動且docker run沒有指定其餘命令時運行;

ENTRYPOINT使用exec方式時,還能夠經過使用CMD的exec方式提供額外的參數,此時CMD的參數列表僅包含參數、再也不有可執行文件。好比:

  • 下面的Dockerfile片斷,ENTRYPOINT ["echo", "hello"] CMD ["world"],會輸出hello world;
  • 若啓動上面的Dockerfile建立的鏡像,啓動命令爲docker run -it [image] cvte,會輸出hello cvte

(3) 構建鏡像

# docker build -t tag_name path_to_Dockerfile
複製代碼

Tips: Dockerfile所在目錄除了須要拷貝到鏡像中的文件外,不要有其餘無關文件或文件夾,即保證Dockerfile所在目錄乾淨。不然構建時可能會出現長時間拷貝致使失敗;

(4) 一個例子

Dockerfile倉庫

四、Registry

Registry是存放Docker鏡像的倉庫,分公有和私有兩種。

(1) DockerHub

DockerHubDocker公司對公衆提供的免費Registry,用戶能夠在上面下載各類類型的應用或鏡像。好比下載一個有Python3環境的鏡像、能夠提供redis存儲服務的服務器。官網地址

(2) 公司內網

出於對速度或安全的考慮,用戶能夠建立本身私有的Registry。公司內網Registry地址

3、Docker管理

除了上面介紹的對容器和鏡像的基本操做外,還可使用docker-compose管理容器。

docker-compose經過一個docker-compose.yml配置文件,完成單個容器的配置(好比鏡像、端口映射、目錄掛載、環境變量等)、多個相互依賴的容器編排(容器啓動順序)等功能。

這塊內容較多而且也不難,有了上文的基礎,經過下文的參考文檔應該能掌握。

4、實現容器的底層技術

cgroupnamespace是實現容器的兩個重要技術。cgroup實現資源限額namespace實現資源隔離

一、cgroup

  • 對容器的資源限制,好比--cpu-shares、-m實際就是在配置cgroup;
  • 在/sys/fs/cgroup/cpu/docker目錄中,會爲每一個容器建立一個cgroup目錄,以容器長ID命名,裏面的若干文件就是與CPU相關的cgroup配置。好比cpu.shares保存的就是--cpu-shares的配置;
  • 同理,/sys/fs/cgroup/memory/docker保存的就是容器內存的cgroup配置;

二、namespace

namespace相對cgroup要難一些。Linux使用了6中namespace,分別對應6種資源:Mount、UTS、IPC、PID、Network、User。

  • Mount namespace: 讓容器看山去擁有整個文件系統,能夠在容器內執行mount,這些操做只會在容器內生效;
  • UTS namespace:讓容器擁有本身的hostname。默認狀況下,容器的hostname是它的短ID,也可使用-h或--hostname指定。
  • IPC namespace:讓容器擁有本身的IPC來實現進程間通訊,不會與主機的IPC混合在一塊兒;
  • PID namespace:容器在宿主機上以進城的形式存在;全部容器進城都掛載dockerd進程下,同時也能夠看到容易內只屬於該容器的子進程;
  • Network namespace:讓容器擁有本身獨立的網卡、IP、路由等資源;
  • User namespace:讓容器可以管理本身的用戶,host不能看到容器中建立的用戶。

參考文檔: Docker--從入門到實踐

相關文章
相關標籤/搜索