走在通往docker的大道上——docker基礎知識彙總html
最後編輯時間:2017年03月09日python
Docker是一種新的容器化技術,爲應用開發和部署提供「一站式」容器解決方案,能幫助開發者高效快速的構建應用,實現「Build,Ship and Run Any App, Anywhere」,從而達到「一次構建,處處運行」的目的。nginx
相信你們都有這樣的遭遇,每次要開發新軟件或者換環境的時候,須要安裝配置一大堆的依賴。雖然有yum或者apt這類的包管理軟件幫忙,可是若是出現的包衝突,或者找不到包的狀況,或者須要源碼編譯卻缺失依賴,這種環境部署簡直就是噩夢。web
Docker就是解決上述噩夢的利器。同時,Docker也解決了跨平臺部署的問題,你能夠在MacOS, Windows, Linux上安裝Docker,而後下載你所須要的Docker鏡像(image)進行程序開發。當你的程序須要發佈的時候,僅僅須要將你的Docker鏡像打包發佈,再也不須要搭建新環境,讓軟件開發流程變得快速簡單。docker
包括但不只限於:shell
對於開發和部署來講,Docker能夠:apache
Docker和虛擬機都是基於軟件的平臺虛擬化技術,其中:編程
徹底虛擬化
,即模擬完整的底層硬件環境特權指令的執行,客戶操做系統無需進行修改。好比咱們經常使用的VirtualBox,VMWare Workstation和Parallels Desktop等虛擬化軟件。也就是說,Docker容器不須要額外的虛擬機管理軟件和虛擬機操做系統層,直接在宿主機操做系統層面上實現虛擬化,從而達到輕量級,高效的目的。flask
Namespace
:隔離技術的第一層,確保 Docker 容器內的進程看不到也影響不到 Docker 外部的進程。Control Groups
:LXC 技術的關鍵組件,用於進行運行時的資源限制。UnionFS(文件系統)
:容器的構件塊,建立抽象層,從而實現 Docker 的輕量級和運行快速的特性。Docker Client
:用戶和 Docker 守護進程進行通訊的接口,也就是 docker 命令。Docker Daemon
:宿主機上用於用戶應答用戶請求的服務。Registry
:註冊服務器,註冊服務器是存放倉庫(Repository
)的具體服務器。Container
:用於運行應用程序的容器,包含操做系統、用戶文件和元數據,至關於鏡像Images的一個運行實例。。Images
:只讀的 Docker 容器模板,簡言之就是系統鏡像文件。DockerFile
:進行鏡像建立的指令文件。簡單來講,Docker 鏡像就是一個只讀的模板。例如:一個鏡像能夠包含一個完整的 ubuntu 操做系統環境,裏面僅安裝了 Apache 或用戶須要的其它應用程序。ubuntu
Docker是創建在Linux內核基礎上的,在目前的主流Linux系統中,都已經原生支持了Docker且使用體驗也最好,固然,在Windows平臺和MacOS系統中也支持Docker,只是須要使用相似Boot2Docker等虛擬化工具來提供Linux支持。
關於在各類平臺上安裝Docker的方法參考 官網 的Docker Docs,這裏再也不贅述。
Docker提供了不少命令來管理鏡像、容器和倉庫。包括:
search
、上傳push
、下載pull
鏡像。images
、inspect
和ps
命令。rmi
和rm
命令。commit
命令和基於Dockerfile
建立鏡像build
命令。run
、exec
和attach
命令。save
和load
,容器的導出導入命令export
和import
具體命令的使用方法使用命令docker --help查看全部命令列表,使用docker COMMAND --help查看具體命令的信息
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
docker images
鏡像是Docker生命週期中的「構建」部分,能夠用來建立 Docker 容器。
輸入 docker images 輸出 REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE hello-world latest 91c95931e552 5 days ago 910 B
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 打斷,而回轉爲後臺執行。
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 參數不能同時使用。
docker rmi
docker rmi <ID>/<name>
刪除全部未打 tag 的鏡像
docker rmi $(docker images -q | awk '/^<none>/ { print $3 }')
刪除全部鏡像
docker rmi $(docker images -q)
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個容器,不論這些容器是運行仍是中止的。
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。
docker start
docker start <ID>/<name>
docker stop
docker stop <ID>/<name>
docker restart
docker restart <ID>/<name>
docker rm
docker rm <ID>/<name>
刪除全部 Docker 容器
docker rm $(docker ps -a -q)
docker commit
docker commit -m='A new image' --author='Aomine' 614122c0aabb aoct/apache2
將當前的 Docker 容器保存爲一個名爲 aoct/apache2 的鏡像。-m指定建立鏡像的提交信息,--author指定鏡像做者,接着是容器ID、目標鏡像倉庫、鏡像名。
docker push
建立docker hub帳戶,將本地的image push 到hub上,這樣其餘人也可使用了。首先咱們先tag 一個image,而後將其push到咱們的repo裏。
docker tag id {username}/{images_name}:v1 docker push {username}/{images_name}
docker history
docker history <image-name>
只能對本地存在的 Docker 鏡像執行這個命令。
當咱們使用 -d參數運行了一個Container的時候,有時候咱們須要進入這個容器進行一些操做。例若有這樣的一個狀況,咱們運行了一個app在一個容器裏,咱們想進入容器看看,這個app運行的狀態,查看log。那們如何進入呢?其實有不少種方法,這裏介紹兩種。
$ docker run -d --name demo ubuntu /usr/bin/top -b $ docker attach demo
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
使用 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
用於導入 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
和 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 #也能夠這樣。
Dockerfile其實是由一行行命令組成的,讓用戶能夠方便的建立自定義鏡像。
Dockerfile大致由四部分組成:
下邊就是一個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
CMDCMD
命令有三種格式:
CMD
命令用於啓動容器時默認執行的命令,CMD
命令能夠包含可執行文件,也能夠不包含可執行文件:不包含可執行文件的狀況下就要用 ENTRYPOINT
指定一個,而後 CMD
命令的參數就會做爲ENTRYPOINT
的參數。
一個
Dockerfile
中只能有一個CMD
,若是有多個,則最後一個生效。CMD
的shell
形式默認調用/bin/sh -c
執行命令。CMD
命令會被Docker
命令行傳入的參數覆蓋:docker run busybox /bin/echo Hello
Docker
會把CMD
裏的命令覆蓋。
ENTRYPOINT
ENTRYPOINT
命令也有兩種格式:
ENTRYPOINT
命令的字面意思是進入點,而功能也恰如其意:他可讓你的容器表現得像一個可執行程序同樣。
一個Dockerfile
中只能有一個ENTRYPOINT
,若是有多個,則最後一個生效。
關於 CMD
和 ENTRYPOINT
的聯繫請看下面的例子
僅僅使用 ENTRYPOINT
:
FROM ubuntu ENTRYPOINT ls -l
docker build -t yumengzhong/lstest .
執行 docker run 306cd7e8408b /etc/fstab
和 docker 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
做爲容器的入口,使用 CMD
給 ENTRYPOINT
增長默認選項:
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
EXPOSEEXPOSE <port> [<port>...]
命令用來指定對外開放的端口。
例如 EXPOSE 80 3306
,開放 80
和 3306
端口。
WORKDIRWORKDIR /path/to/work/dir
配合 RUN
,CMD
,ENTRYPOINT
命令設置當前工做路徑。
能夠設置屢次,若是是相對路徑,則相對前一個 WORKDIR
命令。默認路徑爲/
。
例如:
FROM ubuntu WORKDIR /etc WORKDIR .. WORKDIR usr WORKDIR lib ENTRYPOINT pwd
docker run ID
獲得的結果爲:/usr/lib
USERUSER <UID/Username>
爲容器內指定 CMD
、RUN
、ENTRYPOINT
命令運行時的用戶名或UID
。
VLOUMEVOLUME ['/data']
容許容器訪問容器的目錄、容許容器之間互相訪問目錄。VOLUME
僅僅是容許將某一個目錄暴露在外面,更多的操做還須要依賴 Docker
命令實現。
ENV
參考 export
的用法咧:ENV LC_ALL en_US.UTF-8
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
Docker
若是想升級到最新版的Docker,就用 apt-get
:
$ apt-get upgrade docker-engine
Docker
$ apt-get purge docker-engine $ apt-get autoremove # 自動刪除依賴 $ rm -rf /var/lib/docker
1.Docker學習與和應用系列
2.Flux7 Docker 系列教程
3.Docker 實踐系列
4.個人Docker筆記(補全ing)