For whom
點開這篇文章的童鞋大多數是剛聽過docker這個詞或者是早就聽過這個詞但是卻沒有仔細了解過,但是發現網上的教程又太過理論,初學者難以快速入門或者不知道從何學起,那麼恭喜你,這篇文章就是為你而寫。
Outline
Docker是什麼?先來一段百度百科上的定義:
Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的鏡像中,然後釋出到任何流行的Linux或Windows 機器上,也可以實作虛拟化。容器是完全使用沙箱機制,互相之間不會有任何接口。
上面的一段話總結起來主要有三點:1.docker的作用是可以将項目及其所需環境一起打包起來,完整移植到另外一個機器上。2.docker是一項虛拟化技術,虛拟化的目的是為了在同一個主機上運作多個系統或應用,提高資源使用率。3.docker的産生的多個環境是完全獨立的,不能互相影響。
認識兩個概念
Docker裡有兩個非常重要的概念, images,container,這兩個概念都跟打包好的項目環境有關。簡單來說,images是鏡像,相當于面向對象裡面的類,container是容器,相當于面向對象裡面的執行個體,那麼我們知道類是可以産生執行個體的,但在dcoker裡不同的是 容器也可以生成鏡像.
總體步驟:主機A build鏡像---push到docker hub---主機B pull鏡像
實戰
話不多說,下面就舉個實際例子,來幫助大家快速入門docker python項目部署。
假如我的朋友小Xi(又無中生友了..)是一個深度學習煉丹師,最近在忙活一個人臉檢測項目,經過多次優化,終于得到了一個精度和速度都非常棒的模型,現在他的Leader要讓他給甲方當面展示下模型,甲方提出了一個要求:模型必須在甲方提供的主機上運作,以防乙方得到的模型資料是在硬體配置非常高的環境下得到的。小Xi了解甲方的顧慮,但是這萬一甲方的電腦環境配置有問題,到時候現場示範代碼報錯怎麼弄啊,這時候小Xi的同僚小Liu站出來說,你可以試試docker啊,小Xi一拍腦袋,對啊,docker的作用不正是将項目和依賴環境一起打包嗎,說幹就幹,甩了(暴露了《鬼吹燈》鐵粉的身份)!
本地的項目檔案如下圖所示,我們要給甲方運作的主檔案是evaluate_image.py, 那麼我們接下來的任務是把這個項目用docker打包起來,并上傳到docker_hub,在另一台主機上把這個項目pull下來。
準備工作
當你敲了幾個docker指令你就會發現,docker怎麼這麼煩啊,每次都要root權限,那麼怎麼解決這個問題呢?
groups #檢視現在使用者所在組的組成員,這時候應該是沒有docker的
sudo groupadd docker # 添加docker使用者組
sudo gpasswd -a xi docker #"xi"是自己的使用者名,将你的使用者名加到docker使用者組裡
newgrp docker #更新使用者組
groups #這時再檢視使用者所在組的組成員,發現這時候有docker了,但是很可能你再開一個shell groups還是沒有docker,我弄了好久,電腦重新開機以後就有了.
這時應該就解決了權限問題。
build鏡像
首先按照這樣的方式建立目錄,其中docker_file裡面是所有的項目代碼,Dockerfile是我們自己建立的檔案用于生成鏡像
.
├── docker_file
└── Dockerfile
現在你的目錄應該是這個樣子
下面來填寫Dockerfile的内容:
FROM python:2.7 #你的項目的工作環境
ADD ./docker_file /file #./docker_file是本地的項目的相對路徑, /file是你要建立的鏡像裡面的項目的相對路徑
WORKDIR /file #鏡像的工作路徑
##下面三行用于添加阿裡源,官方源pip安裝速度太慢
RUN pip install -U pip
RUN pip config set global.index-url http://mirrors.aliyun.com/pypi/simple
RUN pip config set install.trusted-host mirrors.aliyun.com:
RUN pip install -r requirements.txt #用pip為鏡像安裝項目的依賴庫
CMD ["python", "/file/evaluate_image.py"] #指定項目主檔案
需要着重關注的是requirements.txt的生成方法,這個檔案裡面包含了項目所有的依賴庫,當然你可以一行一行的打進去,幸運的是,Python裡面提供了一個包可以自動生成項目的依賴庫pipreqs,首先你需要安裝這個庫:
pip install pipreqs
然後cd到項目目錄:
pipreqs ./
這時,你會發現docker_file檔案夾下面出現了一個requirements.txt,打開裡面的内容如下:
tensorflow==1.4.1
easydict==1.9
numpy==1.13.3
切回到docker項目根目錄,使用下面的指令,建立鏡像
用下面的指令檢視目前存在的所有鏡像,我們看到了剛才建立的xi_test鏡像,你會發現,怎麼每個鏡像檔案都這麼大啊,會不會把我的硬碟空間吃完,别擔心,docker采用的技術可以和已有鏡像共享相同的部分,是以實際并沒有占據那麼多空間。
docker images
push鏡像到docker hub
既然本地已經有建立的鏡像了,那麼我們就把它上傳到docker hub,先去docker hub注冊一個賬号,比如我的賬号是xyl123,然後建立一個倉庫,如first,那麼這個倉庫就可以用xyl123/first來指代.
docker login #登入docker
docker tag xi_test xyl123/first #必須給本地鏡像打上這樣的tag标簽,才可以傳到docker hub上
docker push xyl123/first
這時打開自己的docker hub首頁會發現已經存在了剛上傳的image
pull鏡像到本地
經過上面的步驟小Xi已經把自己的鏡像傳到docker hub上面了,隻需要甲方安裝docker環境,并且在示範的時候用甲方的主機把docker hub上的鏡像pull下來就好了。
docker pull xyl123/first #通過運作docker images 你會發現本地多出了一個鏡像,接下來你就可以利用images的相關指令對pull下來的images進行操作了.
運作鏡像
運作鏡像的結果是産生一個container,這個container就是我們的項目及其環境。
docker run -it xyl123/first /bin/bash #運作鏡像,産生一個容器,并以shell的互動形式運作容器.
可以看到我們産生了一個容器,并且進入了該容器,而且進入的檔案夾正是我們在Dockerfile裡面設定的工作目錄/file,一旦進入了容器,你就可以像操作本地檔案的方式操作容器裡的檔案。
[email protected]:/file# 中的50666281fef3是該容器的id,如果你想查一下本地還有哪些容器,可以建立一個終端使用(不要在容器内使用):
docker ps #檢視正在運作的container,
docker ps -a # -a可以檢視所有的container
那如果你想删除、開啟,停止,進入,退出一個容器呢?
docker rm container_id #運作某個container
docker stop container_id #停止某個container
docker start container_id #運作某個container
docker stop container_id #停止某個container
docker exec -it container_id /bin/bash #進入某個container
exit #退出container,退出後容器并不停止,這是和 docker attach container_id 方式進入容器的根本的不同
容器生成鏡像
如果在跟甲方示範的時候,甲方提了一些建議,小 Xi修改了生成的容器的内容,為了将修改之後的環境上傳到docker hub,供後續改進,這時候需要用改好的容器生成一個鏡像。
docker commit 50666281fef3 modified_test_xi
這時候再運作docker images,就可以發現新生成的images了。
容器和本地檔案互傳
假如說,甲方要儲存剛才容器内運作的結果到本地,用docker -ps 指令找到剛才容器對應的name
docker cp epic_elbakyan:/file/image/result/宋茜_2.jpeg ./
這時本地就出現了容器内跑出的結果,這不是宋茜的人臉(大)人頭(長腿)嗎?真的很友善。
如果想反過來的,隻需要颠倒本地和容器位址的位置。
docker cp epic_elbakyan: ./ 宋茜_2.jpeg /file/image/result/
注意上面兩個指令不是在容器内部運作的,是在本地運作的。
日常雞湯
工欲善其事必先利其器,對一個算法工程師而言,每天僅僅沉醉于閱讀paper不可自拔,是遠遠不夠的,要睜開眼睛看看世界,合理利用日新月異的技術幫助自己提高效率,同樣的,對于一個負責落地的開發工程師來說,也應該了解必要的理論知識,提升代碼的準确性。是以想要成為一個領域内極其優秀的人才,理論和工程能力如人之雙腿,缺一不可。