Docker已經火了很長一段時間,最近打算在阿里雲上好好熟悉一下Docker的相關應用,為今后的工作做准備,希望如下圖一樣,Docker技術一飛沖天。
基本概念
Docker是基於Go語言實現的雲開源項目,誕生於2013年初,最初發起者是dotCloud公司,其目標是“Build, Ship and Run Any App, Anywhere”,主要概念包括鏡像、容器、倉庫。Docker引擎的技術是Linux容器(Linux Containers, LXC)技術。容器有效地將由單個操作系統的資源划分到孤立的組中,以便更好地在孤立的組之間平衡有沖突的資源使用需求。
-
鏡像Image:類似於虛擬機鏡像,可以理解為面向Docker引擎的只讀模板,包括文件系統。
獲取鏡像:docker pull NAME[:TAG]
查看鏡像信息: 查看所有鏡像docker images
;查看某個鏡像具體信息docker inspect
添加標簽:docker tag xxx ubuntu:first
搜尋鏡像:docker search xxx
,-s=0
指定星級
刪除鏡像:docker rmi xxx
,一般情況下會刪除鏡像的標簽,而不是文件,當刪除最后一個TAG時則會刪除文件,需要注意。
使用鏡像ID刪除鏡像:-f
刪除可以強制刪除鏡像,推薦做法為先刪除依賴該鏡像的所有容器,之后刪除鏡像,Qdocker rm e81
創建鏡像: 創建鏡像包括3種方式,基於已有鏡像的容器創建,首先啟動一個鏡像docker run -ti ubuntu:14.04 /bin/bash
,任意創建一個test文件,之后創建鏡像docker commit -m "add file" -a "xionger" a9fdsfxx test
;基於本地模板創建,推薦使用OpenVZ提供的模板來創建;基於Dockerfile創建。
存出鏡像和載入鏡像(導出、導入): 導出到本地文件sudo docker save -o ubuntu_14.04.tar ubuntu:14.04
,導入鏡像docker load --input ubuntu_14.04.tar
上傳鏡像:docker push NAME[:TAG]
,默認上傳鏡像到DockerHub官方倉庫,需要登錄。 -
容器Container:類似一個輕量級的沙箱,可以利用容器來運行和隔離應用,容器從鏡像啟動時會在鏡像的最上層創建一個可寫層,鏡像本身保持不變。
創建容器:docker create -it ubuntu:lastest
,通過docker ps -a
查看容器,通過docker start
啟動容器
新建並啟動容器:docker run ubuntu /bin/bash
,-d
參數守護態運行,通過Ctrl+d或者exit退出容器
終止容器:docker stop xxx
,首先會發送SIGTERM信號,一段時候后發送SIGKILL,可以通過docker kill
強行中止,docker restart
可以關閉並重啟容器,docker ps -a -q
可以查看處於終止態的容器信息。
進入容器:docker attach xxx
會被阻塞不推薦使用;docker exec -ti xxx /bin/bash
可以直接在容器中運行命令;nsenter工具。
刪除容器:docker rm xxx
,需要注意區分,rmi
是刪除鏡像,rm
是刪除容器
導入和導出容器:docker export xxx
導出一個已經創建的容器到文件,不管是否在運行;docker import
,需要理解的是export
的是快照,信息少,而save
的是鏡像,信息多,包含元數據和歷史信息。
-
倉庫Repository:類似於代碼倉庫,是Docker存放鏡像的場所,而Registry注冊服務器是存放倉庫的地方,其上放着很多倉庫,每個倉庫集中存放某一類鏡像的多個文件,可以通過tag標簽來區分。目前最大的公有倉庫是Docker Hub,而國內是Docker Pool。
Docker Pub:本地用戶目錄.dockercfg中存儲登錄信息,在倉庫中存在centos這類由Docker公司創建、驗證、支持的根鏡像,也有類似xionger/centos這類由個人提供的鏡像,可以通過-s N
來查看高星鏡像。此外,Docker Hub還可以通過設置追蹤類似GitHub的網站,然后根據其更行,自動執行創建。
創建和使用私有倉庫:可以通過官方提供的registry
鏡像來簡單搭建一套本地私有倉庫環境。docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry docker images docker tag ubuntu:14.04 139.196.96.27:5000/test docker push 139.196.xx.xx:5000/test curl http://139.196.xx.xx:5000/v1/search docker pull 139.196.xx.xx:5000/test
Tip:
CURL(CommandLine Uniform Resource Locator):curl是利用URL語法在命令行方式下工作的開源文件傳輸工具。
安裝Docker(Ubuntu16.04),默認安裝在/var/lib/docker
sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install -y docker.io
Tip:
在用putty連接阿里雲時,經常會斷開,如何解決?
解決方法:在Connection里面有個Seconds between keepaliaves。這里就是每間隔指定的秒數,就給服務器發送一個空的數據包,來保持連接。以免登錄的主機那邊在長時間沒接到數據后,會自動斷開SSH的連接,設置為10。
阿里雲購買ECS, 操作系統版本Ubuntu 16.04(LTS)
進階概念
數據管理:在使用docker過程中,會涉及查看容器內應用產生的數據,或者數據在多個容器間共享,此時需要管理數據的兩種方式包括數據卷Data Volumes和數據卷容器Data Volume Containers.
數據卷:是一個可供容器使用的特殊目錄,繞過文件系統,具有的特性包括數據卷可以在容器之間共享和重用、對數據卷的修改會馬上生效、對數據卷的更新不會影響鏡像、卷會一致存在,知道沒有容器使用,類似Linux下對目錄或文件進行mount操作。
在容器內創建一個數據卷:使用training/webapp
鏡像創建一個web容器,並創建一個數據卷掛在到容器的/webapp目錄,docker run -d -P --name web -v /webapp python app.py
。
掛載一個主機目錄作為數據卷:加載主機的/src/webapp
目錄到容器的/opt/webapp
目錄,docker run -d -P --name web - v /src/webapp:/opt/webapp training/webapp python app.py
。
Tip:編輯工具包括vi或者sed --in-place,推薦掛載目錄而不是文件,因為inode變化會造成docker容器啟動失敗。
數據卷容器:其實就是一個普通的容器,其中會掛載數據卷用戶共享,創建數據庫容器dbdata,之后其他容器將掛載可以掛載該數據卷容器中的數據卷。
docker run -it -v /dbdata --name dbdata ubuntu
ls
docker run -it --volumes-from dbdata --name db1 ubuntu
利用數據卷容器遷移數據:可以通過數據卷容器對其中的數據卷進行備份、回復,以實現數據的遷移。接下來的示例利用ubuntu鏡像創建一個容器worker,使用--volumes-from dbdata
參數掛載dbdata容器的數據卷,
使用-v ${pwd}:/backup
參數來掛載本地的當前目錄到worker容器的/backup
目錄,
容器啟動后,使用tar cvf /backup/backup.tar /dbdata
來講/dbdata
下內容備份為容器內的/backup/backup.tar
。
docker run --volumes-from dbdata -v ${pwd}:/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata
//恢復,首先創建一個帶有數據卷的容器dbdata2,之后 創建另一個新的容器,掛載dbdata2容器,並使用untar解壓備份文件到所掛載的容器卷中即可
docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
docker run --volumes-from dbdata2 -v ${pwd}:/backup busybox tar xvf /backup/backup.tar
在生產環境,推薦使用分布式文件系統Ceph、GPFS、HDFS定期對主機的本地數據進行備份。
網絡基礎配置:
端口映射實現訪問容器:在啟動容器時,如果不指定對應參數,在容器外部是無法通過網絡來訪問容器內的網絡應用和服務的。可以使用-p ip:hostPort:containerPort
映射端口,docker logs
查看應用的信息,docker port
查看端口配置。
docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
容器互聯實現容器間通信:容器見的連接系統是除了端口映射外另一種可以與容器中應用進行交互的方式,它會在源和接受容器間創建一個隧道,接受容器可以看到源容器制定的信息,比如--link
連接應用容器和數據庫容器,這樣可以保證db的接口不暴露到公網。
docker run -d -P --name web training/webapp python app.py
docker ps -l
docker inspect -f xxx
//容器互聯
docker run -d --name db training/postgres
docker rm -f web
docker run -d -P --name web --link db:db training/webapp python app.py
docker ps
Docker通過兩種方式為容器公開連接信息,包括環境變量env
和/etc/hosts文件,通過apt-get install -yqq inetutils-ping
安裝ping。
擴展知識:Docker已有的實現PaaS的項目有Deis、Flynn等,持續集成方面有Drone,管理工具有Citadel, Shipyard, DockerUI等。
使用Dockerfile創建鏡像
基本結構:dockerfile由命令語句組成,支持#開頭的注釋,分為4個部分,包括基礎鏡像信息、維護者信息、鏡像操作指令和容器啟動執行指令,在docker hub上有很多dockerfile的demo,需要時可以直接使用。
#基礎鏡像
FROM ubuntu
#維護者信息
MAINTAINER xionger xiongere@email.com
#鏡像的操作指令
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
#容器啟動時執行指令
CMD /usr/sbin/nginx
指令:一般格式為INSTRUCTION arguments,具體如下所示。
FROM <image>:<tag>
默認的第一條指令
MAINTAINER <name>
維護者信息
RUN <command>
或者RUN ["executable", "param1", "param2"]
,前者將在shell終端中運行命令,即/bin/sh -c
,后者則使用exec
執行。
CMD ["executable", "param1", "param2"]
使用exec
執行,推薦方式。
EXPOSE <port> [<port>..]
告訴Docker服務器容器暴露的端口號,供互聯網系統使用。
ENV <key> <value>
指定一個環境變量,會被后續的RUN
指令使用
ADD <src> <dest>
該命令將復制指定
COPY
<src> <dest>
復制本地主機
<src>
到容器中
<dest>
,推薦使用
ENTRYPOINT
["executable", "param1", "param2"]
配置容器啟動后執行的命令,不能被
docker run
提供的參數覆蓋
VOLUME
["/data"]
創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據。
USER
daemon
指定運行容器時的UID,后續的
RUN
也會使用指定用戶,如
RUN group add -r postgres && useradd -r -g postgres postgres
,要獲取管理員權限時可以使用
gosu
而不是
sudo
WORKDIR
path/to/workdir
為后續的指令配置工作目錄
ONBUILD
[INSTRUCTION]
配置當所創建的鏡像作為其他新創建鏡像的基礎鏡像時,所執行的操作指令。
創建鏡像:編寫好dockerfile后,可以通過docker build
命令來創建鏡像,該命令將讀取指定路徑下(包括子目錄)的dockerfile,並將該路徑下所有內容發送給docker服務端,由服務端來創建鏡像,此外可以通過.dockerignore
文件來忽略目錄或文件,還可以通過-t
指定鏡像的標簽信息。示例docker build -t build_repo/first_image /tmp/docker_builder/
實踐之道
操作系統:CentOS和Ubuntu都可以,個人喜好ubuntu(還可以選用debian:jessie, alpine),屬於最基礎的鏡像。
tip: 當試圖安裝軟件出現沒有相關包信息時,需要apt-get update
或編輯/etc/apt/sources.list
文件(deb, deb-src
,需要時在查詢,比如163的鏡像,阿里雲的話無需設置),可以通過netstat -tunlp
查看當前網絡情況。
支持SSH:當需要直接進入容器進行管理時安裝,不必須。
Web服務器與應用(Nginx,可以使用淘寶優化的Tengine代替Nginx,Tomcat):在/usr/docker
下創建tomcat
,nginx
目錄應用存放Dockerfile文件,最終還是選擇通過pull拉去鏡像的方式安裝應用,dockerfile比較復雜。
docker pull nginx:1.12
docker ps -a
//-p 80:80:將容器的80端口映射到主機的80端口
//-name mynginx:將容器命名為mynginx
//-v $PWD/www:/www:將主機中當前目錄下的www掛載到容器的/www
//-v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf:將主機中當前目錄下的nginx.conf掛載到容器的/etc/nginx/nginx.conf
//-v $PWD/logs:/wwwlogs:將主機中當前目錄下的logs掛載到容器的/wwwlogs
docker run --name nginx01 -p 80:80 -v $PWD/www:/www -v $PWD/conf:/etc/nginx -v $PWD/logs:/wwwlogs -d nginx:1.12
docker pull tomcat:8.0
docker run --name tomcat01 -p 8080:8080 -v $PWD/test:/usr/local/tomcat/webapps/test -d tomcat:8.0
tip:
有時可能需要重啟docker服務, service docker restart
,可以選擇tomcat7.0:jdk1.8
nginx配置詳解
nginx官方文檔
數據庫應用MySQL(5.6), MongoDB(3.2), Redis(3.2)
docker pull mysql
docker run -p 3306:3306 --name mysql01 -v $PWD/conf:/etc/mysql -v $PWD/logs:/logs -v $PWD/data:/mysql_data -e MYSQL_ROOT_PASSWORD=123456 -d mysql
//主從模式
docker run -p 3306:3306 --name mysql01 -v $PWD/conf01:/etc/mysql -v $PWD/logs01:/logs -v $PWD/data01:/mysql_data -e MYSQL_ROOT_PASSWORD=123456 -e REPLICATION_MASTER=true -d mysql
docker run -p 3307:3306 --name mysql02 -v $PWD/conf02:/etc/mysql -v $PWD/logs02:/logs -v $PWD/data02:/mysql_data -e MYSQL_ROOT_PASSWORD=123456 -e REPLICATION_SLAVE=true --link mysql01:mysql01 -d mysql
//mongodb,暫時單機,其默認提供集群的配置
docker pull mongo:3.2
docker run -p 27017:27017 -p 28017:28017 --name mongodb01 -v $PWD/db01:/data/db -e MONGODN_PASS="123456" -d mongo:3.2
//redis
docker pull redis:3.2
docker run -p 6379:6379 --name redis01 -v $PWD/data01:/data -d redis:3.2 redis-server --appendonly yes
tip:可以進入db的容器進行操作,docker exec -ti mysql /bin/bash
其他應用:maven, gitlab, jenkins, dubbo, cat,具體內容將在之后的文章中陸續介紹。
docker pull jenkins:2.60.1
docker run --name jenkins01 -p 9090:8080 -p 9091:50000 -v $PWD/jenkins01:/var/jenkins_home -d jenkins:2.60.1
構建Docker容器集群:核心問題就是讓不同主機中的Docker容器相互訪問,簡單的方式包括兩種。使用自定義網橋連接跨主機容器,Docker默認的網橋是docker0,可以通過brctl show
查看。使用Ambassador容器:當2個docker容器再同意主機時,可以通過--link相互訪問,如果需要跨主機實現,則需要知道其他物理主機的IP地址。
Docker CI集成方案:在之后的Jenkins一文中將重點分析。
Tip:
目前百度BAE已經在生產環境使用Docker,Airbnb,ebay已使用mesos集成docker部署應用,此外可以使用apparmor對容器的能力進行限制。
個人目前實踐計划
私有Docker倉庫暫時不建立,先使用DockerHub;Git類似,先使用Github;Maven需要使用Nexus建立一個私有庫;jenkins之間搭建就好。
參考資料
- 楊保華. Docker技術入門與實踐[M]. 北京:機械工業出版社, 2016.
- Docker常見安裝指南