一篇文章帶你掌握docker基礎知識

走在通往docker的大道上——docker基礎知識彙總html

最後編輯時間:2017年03月09日python


1.Docker是什麼

Docker是一種新的容器化技術,爲應用開發和部署提供「一站式」容器解決方案,能幫助開發者高效快速的構建應用,實現「Build,Ship and Run Any App, Anywhere」,從而達到「一次構建,處處運行」的目的。nginx

2.爲何Docker

相信你們都有這樣的遭遇,每次要開發新軟件或者換環境的時候,須要安裝配置一大堆的依賴。雖然有yum或者apt這類的包管理軟件幫忙,可是若是出現的包衝突,或者找不到包的狀況,或者須要源碼編譯卻缺失依賴,這種環境部署簡直就是噩夢。web

Docker就是解決上述噩夢的利器。同時,Docker也解決了跨平臺部署的問題,你能夠在MacOS, Windows, Linux上安裝Docker,而後下載你所須要的Docker鏡像(image)進行程序開發。當你的程序須要發佈的時候,僅僅須要將你的Docker鏡像打包發佈,再也不須要搭建新環境,讓軟件開發流程變得快速簡單。docker

3.Docker的特點

包括但不只限於:shell

  • 物美價廉
  • 輕量級和便攜化
  • 低CPU 和內存使用
  • 啓動、運行、關閉速度快
  • 能夠用來做爲雲計算的基礎

對於開發和部署來講,Docker能夠:apache

  • 更快速的交付和部署應用環境
  • 更高效的資源利用率
  • 更便捷的遷移和擴展性
  • 更便捷的應用更新管理

4.Docker與虛擬機

Docker和虛擬機都是基於軟件的平臺虛擬化技術,其中:編程

  • 虛擬機屬於徹底虛擬化,即模擬完整的底層硬件環境特權指令的執行,客戶操做系統無需進行修改。好比咱們經常使用的VirtualBox,VMWare Workstation和Parallels Desktop等虛擬化軟件。
  • Docker和其它容器技術即是操做系統級虛擬化,即直接經過內核建立虛擬的操做系統實例(內核和庫),來隔離不一樣的進程和資源。

也就是說,Docker容器不須要額外的虛擬機管理軟件和虛擬機操做系統層,直接在宿主機操做系統層面上實現虛擬化,從而達到輕量級,高效的目的。flask

clipboard.png

5.Docker核心概念

Docker底層組成:

  • Namespace:隔離技術的第一層,確保 Docker 容器內的進程看不到也影響不到 Docker 外部的進程。
  • Control Groups:LXC 技術的關鍵組件,用於進行運行時的資源限制。
  • UnionFS(文件系統):容器的構件塊,建立抽象層,從而實現 Docker 的輕量級和運行快速的特性。

Docker的主要構成:

  • Docker Client:用戶和 Docker 守護進程進行通訊的接口,也就是 docker 命令。
  • Docker Daemon:宿主機上用於用戶應答用戶請求的服務。
  • Registry:註冊服務器,註冊服務器是存放倉庫(Repository)的具體服務器。

Docker的三元素:

  • Container:用於運行應用程序的容器,包含操做系統、用戶文件和元數據,至關於鏡像Images的一個運行實例。。
  • Images:只讀的 Docker 容器模板,簡言之就是系統鏡像文件。
  • DockerFile:進行鏡像建立的指令文件。

clipboard.png

簡單來講,Docker 鏡像就是一個只讀的模板。例如:一個鏡像能夠包含一個完整的 ubuntu 操做系統環境,裏面僅安裝了 Apache 或用戶須要的其它應用程序。ubuntu

6.Docker安裝

Docker是創建在Linux內核基礎上的,在目前的主流Linux系統中,都已經原生支持了Docker且使用體驗也最好,固然,在Windows平臺和MacOS系統中也支持Docker,只是須要使用相似Boot2Docker等虛擬化工具來提供Linux支持。

關於在各類平臺上安裝Docker的方法參考 官網 的Docker Docs,這裏再也不贅述。

7.Docker基礎命令

Docker提供了不少命令來管理鏡像、容器和倉庫。包括:

  • 從Docker Hub倉庫中查找search、上傳push、下載pull鏡像。
  • 查看本地已有鏡像、容器信息的imagesinspectps命令。
  • 刪除本地鏡像和容器的rmirm命令。
  • 基於已有容器建立鏡像的commit命令和基於Dockerfile建立鏡像build命令。
  • 運行、進入容器的runexecattach命令。
  • 鏡像的保存和導入命令saveload,容器的導出導入命令exportimport

具體命令的使用方法使用命令docker --help查看全部命令列表,使用docker COMMAND --help查看具體命令的信息

clipboard.png

8.基礎命令詳解

1.檢查安裝 docker info

若是 Docker 沒有安裝,會提示command not found,若是 Docker 已經成功安裝,則會有相似以下的提示:

輸入
docker info

輸出
Containers: 2
Images: 2
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 6
 Dirperm1 Supported: false
Execution Driver: native-0.2
Kernel Version: 3.13.0-24-generic
Operating System: Ubuntu 14.04 LTS
CPUs: 1
Total Memory: 979.6 MiB
Name: ubuntu
ID: PRLX:CY3O:TZ6P:4UAS:VDWM:MHWB:FB3V:TJBJ:GQ4J:Q453:GPOY:WZSI
WARNING: No swap limit support

2. 查看本地鏡像 docker images

鏡像是Docker生命週期中的「構建」部分,能夠用來建立 Docker 容器。

輸入 
docker images

輸出
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world         latest              91c95931e552        5 days ago          910 B

3. 下載鏡像 docker pull <image name>

輸入
docker pull busybox

輸出
latest: Pulling from busybox
cf2616975b4a: Pull complete
6ce2e90b0bc7: Pull complete
8c2e06607696: Already exists
busybox:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:38a203e1986cf79639cfb9b2e1d6e773de84002feea2d4eb006b52004ee8502d
Status: Downloaded newer image for busybox:latest

busybox 是一個 Linux 工具集,包括各類經常使用命令,例如 cat、echo ,也有各類高級命令,例如 grep、mount 等。執行完 docker pull busybox 以後,Docker 會自動從 Docker 官方下載 busybox 的鏡像文件。

這個過程當中能夠執行 Ctrl+C,docker pull 不會由於 Ctrl+C 打斷,而回轉爲後臺執行。

4. 運行鏡像 docker run <image name>

輸入 
docker run busybox /bin/echo Hello Docker

輸出
Hello Docker

這條命令是運行 busybox 鏡像中的 /bin/echo 命令,參數是 Hello Docker

其餘標誌:

-i 保證容器的stdin開啓
-t 爲容器生成一個tty終端
-d 表示後臺運行
--rm=true 容器終止後刪除
--name name 表示 container 的名稱
-v 將目錄掛載到 container
--privileged=true 防止沒有權限訪問掛載的目錄
-p 9998:80 指定端口映射
--link name:container 與其餘 container 連接.
--icc=true 去除 container 之間不互通. 須要放在 run 前面.

注意,--rm 和 -d 參數不能同時使用。

5.刪除鏡像 docker rmi

docker rmi <ID>/<name>

刪除全部未打 tag 的鏡像

docker rmi $(docker images -q | awk '/^<none>/ { print $3 }')

刪除全部鏡像

docker rmi $(docker images -q)

6. 查看本地容器 docker ps

docker ps 查看正在運行的容器

輸入 
docker ps

輸出
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world         latest              91c95931e552        1 days ago          910 B

docker ps -a 查看全部的容器,-q 返回 id

docker ps -a -q

docker ps -n x 該命令會顯示最後x個容器,不論這些容器是運行仍是中止的。

7. 查詢輸出docker logs <ID>/<name>

查詢容器的輸出內容:

例如:經過 docker logs 命令查詢 sample_job 對應的容器的輸出內容。

sample_job=$(docker run -d busybox /bin/sh -c "while true; do echo Docker; sleep 1; done")
輸入 
docker logs $sample_job

輸出
Docker
Docker
Docker
Docker

只要這個容器運行的時間足夠長,就會輸出足夠多行的 Docker。

8. 啓動容器docker start

docker start <ID>/<name>

9. 中止容器docker stop

docker stop <ID>/<name>

10. 重啓容器docker restart

docker restart <ID>/<name>

11.刪除容器 docker rm

docker rm <ID>/<name>

刪除全部 Docker 容器

docker rm $(docker ps -a -q)

12.保存容器docker commit

docker commit -m='A new image' --author='Aomine' 614122c0aabb aoct/apache2

將當前的 Docker 容器保存爲一個名爲 aoct/apache2 的鏡像。-m指定建立鏡像的提交信息,--author指定鏡像做者,接着是容器ID、目標鏡像倉庫、鏡像名。

13. 鏡像上傳docker push

建立docker hub帳戶,將本地的image push 到hub上,這樣其餘人也可使用了。首先咱們先tag 一個image,而後將其push到咱們的repo裏。

docker tag id {username}/{images_name}:v1
docker push {username}/{images_name}

14. 獲取鏡像歷史docker history

docker history <image-name>

只能對本地存在的 Docker 鏡像執行這個命令。

15.進入容器

當咱們使用 -d參數運行了一個Container的時候,有時候咱們須要進入這個容器進行一些操做。例若有這樣的一個狀況,咱們運行了一個app在一個容器裏,咱們想進入容器看看,這個app運行的狀態,查看log。那們如何進入呢?其實有不少種方法,這裏介紹兩種。

1.docker attach <ID>/<name>
$ docker run -d --name demo ubuntu /usr/bin/top -b
$ docker attach demo
2.docker exec <ID>/<name>
docker exec -i -t webapp /bin/bash

docker attach 和 docker exec區別

docker attach讓用戶能夠進入Container查看輸出等等操做,可是並不會另外啓動一個進程! 若是你用CTRL-c來退出,同時這個信號會kill Container(默認狀況)

docker exec 會啓動另一個進程來進入Container,這裏的操做是在這個進程下的。若是你用CTRL-c來退出,不會kill 原來的Container

16.鏡像的導入與導出load & save

使用 load 從 stdin 導入一個 tar 格式的鏡像或者倉庫,而後用 save 將 tar 鏡像輸出到 stdout。

docker save -o <output file> <image>或者docker save <image> > <output file>
docker load -i <file name>或者docker load < <file name>

這兩個命令經常使用於多節點部署。

例如:

命令 # docker save -o a.tar suse
命令 # docker load -i a.tar

17.容器導入import

用於導入 URL / 文件,從本地導入須要 - 參數。docker import [OPTIONS] URL|- [REPOSITORY[:TAG]]、URL/-二選一。

命令# docker import http://mirrors.ustc.edu.cn/openvz/template/precreated/suse-13.1-x86-minimal.tar.gz suse:minimal  #這裏使用的是ustc鏡像源。
Downloading from http://mirrors.ustc.edu.cn/openvz/template/precreated/suse-13.1-x86-minimal.tar.gz
127a9e7b9f87e4fc280c96bee9fad0a19057de38d307fe7fc1f6d35c86f1aff657.89 MB/57.89 MB
命令# docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
suse                     minimal             127a9e7b9f87        2 minutes ago       149.1 MB

導入本地鏡像:

cat suse-13.1-x86-minimal.tar.gz |docker import - suse:minmal

18.容器導出export

和 import 相反,export 將容器導出成 tar 壓縮包。

例如

命令 # docker run -i -t -d suse:minimal /bin/bash
060f6e6c877af01313363b6506107438b9eb5ba87a7ef0625577e348a554ecca
命令 # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
060f6e6c877a        suse:minimal        "/bin/bash"         2 seconds ago       Up 2 seconds                            fervent_ritchie
命令 # docker export -o a.tar 060f
命令 # docker export 060f > a.tar  #也能夠這樣。

9.什麼是Dockerfile

Dockerfile其實是由一行行命令組成的,讓用戶能夠方便的建立自定義鏡像。

Dockerfile大致由四部分組成:

  • 指明基礎鏡像指令FROM
  • 維護者信息指令MAINTAINER
  • 鏡像操做指令RUN、EVN、ADD和WORKDIR等
  • 容器啓動時的執行指令CMD、ENTRYPOINT和USER等

下邊就是一個Dockerfile的例子

FROM python:2.7
MAINTAINER yumengzhong <760042201@qq.com>
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["python"]
CMD ["app.py"]
1. 從dockerhub上pull下python 2.7的基礎鏡像。
 2. 維護者的信息
 3. copy當前目錄到容器中的 /app目錄下  複製本地主機的<src>(Dockerfile所在目錄的相對路徑)到容器裏<dest>
 4. 指定工做路徑爲/app
 5. 安裝依賴
 6. 暴露5000端口
 7. 啓動app

這個例子是啓動一個python flask app的Dockerfile(flask是python的一個輕量的web框架)。

下邊我就來介紹下dockerfile裏經常使用的指令。

格式
Dockerfile 中全部的命令都是如下格式:INSTRUCTION argument
指令(INSTRUCTION)不分大小寫,可是推薦大寫。

FROM
用於指定基礎的images

格式爲 FROM <image> or FORM <image>:<tag>

全部的 Dockerfile 都用該以 FROM 開頭,FROM 命令指明 Dockerfile 所建立的鏡像文件以什麼鏡像爲基礎,FROM 之後的全部指令都會在 FROM 的基礎上進行建立鏡像;能夠在同一個 Dockerfile 中屢次使用 FROM 命令用於建立多個鏡像。

MAINTAINER
格式爲 MAINTAINER <name> 用於指定鏡像建立者和聯繫方式。

MAINTAINER yumengzhong <760042201@qq.com>

RUN
格式爲 RUN <command>
用於容器內部執行命令。每一個 RUN 命令至關於在原有的鏡像基礎上添加了一個改動層,原有的鏡像不會有變化。

ADD
格式爲 ADD<src><dest> 將主機文件複製到容器中

該命令將複製指定的 <src> 到容器中的 <dest>。其中 <src> 能夠是Dockerfile所在目錄的一個相對路徑,能夠是文件或目錄的路徑,也能夠是一個URL,還能夠是一個 tar 文件(自動解壓爲目錄)。

ADD /path/to/sourcefile/in/host /path/to/targetfile/in/container

COPY
格式爲 COPY <src><dest>

複製本地主機的 <src>(爲 Dockerfile 所在目錄的相對路徑)到容器中的 <dest>

當使用本地目錄爲源目錄時,推薦使用 COPY

CMD
CMD 命令有三種格式:

  • CMD ["executable","param1","param2"]:推薦使用的 exec 形式。
  • CMD ["param1","param2"]:無可執行程序形式
  • CMD command param1 param2:shell 形式。

CMD 命令用於啓動容器時默認執行的命令,CMD 命令能夠包含可執行文件,也能夠不包含可執行文件:不包含可執行文件的狀況下就要用 ENTRYPOINT 指定一個,而後 CMD 命令的參數就會做爲ENTRYPOINT的參數。

一個 Dockerfile 中只能有一個CMD,若是有多個,則最後一個生效。
CMDshell 形式默認調用 /bin/sh -c 執行命令。
CMD 命令會被 Docker 命令行傳入的參數覆蓋:docker run busybox /bin/echo Hello Docker 會把 CMD 裏的命令覆蓋。

ENTRYPOINT

ENTRYPOINT 命令也有兩種格式:

  • ENTRYPOINT ["executable", "param1", "param2"] :推薦使用的 exec 形式
  • ENTRYPOINT command param1 param2 :shell 形式

ENTRYPOINT 命令的字面意思是進入點,而功能也恰如其意:他可讓你的容器表現得像一個可執行程序同樣。
一個 Dockerfile 中只能有一個 ENTRYPOINT,若是有多個,則最後一個生效。

關於 CMDENTRYPOINT 的聯繫請看下面的例子

僅僅使用 ENTRYPOINT

FROM ubuntu
ENTRYPOINT ls -l
docker build -t yumengzhong/lstest .

執行 docker run 306cd7e8408b /etc/fstabdocker run 306cd7e8408b 結果並不會有什麼差異:

命令 # docker run 306cd7e8408b /etc/fstab
total 64
drwxr-xr-x   2 root root 4096 Mar 20 05:22 bin
drwxr-xr-x   2 root root 4096 Apr 10  2014 boot
drwxr-xr-x   5 root root  360 Apr 24 02:52 dev
drwxr-xr-x  64 root root 4096 Apr 24 02:52 etc
drwxr-xr-x   2 root root 4096 Apr 10  2014 home
……

可是咱們一般使用 ENTRYPOINT 做爲容器的入口,使用 CMDENTRYPOINT 增長默認選項

FROM ubuntu
CMD ["-l"]
ENTRYPOINT ["ls"]

而後執行這個容器:
不加參數便會默認有 -l參數:

命令 # docker run 89dc7e6d0ac1
total 64
drwxr-xr-x   2 root root 4096 Mar 20 05:22 bin
drwxr-xr-x   2 root root 4096 Apr 10  2014 boot
drwxr-xr-x   5 root root  360 Apr 24 02:47 dev
drwxr-xr-x  64 root root 4096 Apr 24 02:47 etc
drwxr-xr-x   2 root root 4096 Apr 10  2014 home
drwxr-xr-x  12 root root 4096 Mar 20 05:21 lib
drwxr-xr-x   2 root root 4096 Mar 20 05:20 lib64
drwxr-xr-x   2 root root 4096 Mar 20 05:19 media
drwxr-xr-x   2 root root 4096 Apr 10  2014 mnt
drwxr-xr-x   2 root root 4096 Mar 20 05:19 opt
dr-xr-xr-x 386 root root    0 Apr 24 02:47 proc
drwx------   2 root root 4096 Mar 20 05:22 root
drwxr-xr-x   7 root root 4096 Mar 20 05:21 run
drwxr-xr-x   2 root root 4096 Apr 21 22:18 sbin
drwxr-xr-x   2 root root 4096 Mar 20 05:19 srv
dr-xr-xr-x  13 root root    0 Apr 24 02:47 sys
drwxrwxrwt   2 root root 4096 Mar 20 05:22 tmp
drwxr-xr-x  11 root root 4096 Apr 21 22:18 usr
drwxr-xr-x  12 root root 4096 Apr 21 22:18 var

加了 /etc/fstab 參數便會覆蓋原有的 -l 參數:

命令 # docker run 89dc7e6d0ac1 /etc/fstab
/etc/fstab

EXPOSE
EXPOSE <port> [<port>...] 命令用來指定對外開放的端口。
例如 EXPOSE 80 3306,開放 803306 端口。

WORKDIR
WORKDIR /path/to/work/dir 配合 RUNCMDENTRYPOINT 命令設置當前工做路徑。
能夠設置屢次,若是是相對路徑,則相對前一個 WORKDIR 命令。默認路徑爲/

例如:

FROM ubuntu
WORKDIR /etc
WORKDIR ..
WORKDIR usr
WORKDIR lib
ENTRYPOINT pwd

docker run ID 獲得的結果爲:/usr/lib

USER
USER <UID/Username> 爲容器內指定 CMDRUNENTRYPOINT 命令運行時的用戶名或UID

VLOUME
VOLUME ['/data'] 容許容器訪問容器的目錄、容許容器之間互相訪問目錄。
VOLUME 僅僅是容許將某一個目錄暴露在外面,更多的操做還須要依賴 Docker 命令實現。

ENV
參考 export 的用法咧:
ENV LC_ALL en_US.UTF-8

10.構建dockerfile

Dockerfile 的寫法已經講述完畢,來看示例:

實例一

mkdir static_web
cd static_web
touch Dockerfile
而後 vi Dockerfile  開始編輯該文件
輸入 i 開始編輯

FROM nginx
MAINTAINER yumengzhong "760042201@qq.com"
ENV REFRESHED_AT 2017-03-03
RUN echo '<h1>hello,<a href="http://www.imooc.com">慕課網</a>!</h1>' >  /usr/share/nginx/html/index.html

編輯完後 按 esc 退出編輯
而後  :wq    寫入 退出

補充

:q! 強行退出(不存盤)
:wq 強制性寫入文件並退出。即便文件沒有被修改也強制寫入,並更新文件的修改時間。
:x 寫入文件並退出。僅當文件被修改時才寫入,並更新文件修改時間,不然不會更新文件修改時間。
ESC鍵只能切換到命令狀態

:x:wq 的真正區別
:wq 強制性寫入文件並退出。即便文件沒有被修改也強制寫入,並更新文件的修改時間。
:x 寫入文件並退出。僅當文件被修改時才寫入,並更新文件修改時間,不然不會更新文件修改時間。

這二者通常狀況下沒什麼不同,可是在編程方面,對編輯源文件可能會產生重要影響。由於文件即便沒有修改,:wq 強制更新文件的修改時間,這樣會讓 make 編譯整個項目時覺得文件被修改過了,而後就得從新編譯連接生成可執行文件。這可能會產生讓人誤解的後果,固然也產生了沒必要要的系統資源花銷。

docker build -t yumengzhong/nginx_web:v1 .

-t是爲新鏡像設置倉庫和名稱,其中yumengzhong爲倉庫名,nginx_web爲鏡像名,:v1爲標籤(不添加爲默認latest)

docker run --name nginx_web -d -p 82:80 yumengzhong/nginx_web:v1

遊覽器 192.168.99.100:82或localhost:82

實例二

#Dockerfile
FROM centos6-base
#指定centos6系統
MAINTAINER zhou_mfk <zhou_mfk@163.com>
#我抄的他的 Dockerfile
RUN ssh-keygen -q -N "" -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key
#建立私鑰
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
#修復SSH登陸,不然登錄後的用戶會被秒退。
RUN mkdir -p /root/.ssh && chown root.root /root && chmod 700 /root/.ssh
#建立root用戶的ssh文件夾
EXPOSE 22
#開放端口
RUN echo 'root:redhat' | chpasswd
#root用戶改密碼爲redhat
RUN yum install -y yum-priorities && rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm && rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
RUN yum install tar gzip gcc vim wget screen -y
#安裝epel和安裝一些軟件
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
#系統環境變量
CMD ["/usr/sbin/sshd", "-D"]
#啓動sshd
#End

11.升級Docker

若是想升級到最新版的Docker,就用 apt-get

$ apt-get upgrade docker-engine

12.卸載Docker

$ apt-get purge docker-engine
$ apt-get autoremove # 自動刪除依賴
$ rm -rf /var/lib/docker

參考&引用

1.Docker學習與和應用系列
2.Flux7 Docker 系列教程
3.Docker 實踐系列
4.個人Docker筆記(補全ing)

相關文章
相關標籤/搜索