一:Docker介紹
• Docker簡介
Docker是2013發起的一個專案,早在2013年,Docker自誕生起,就是整個技術界的明星專案,很多技術媒體宣稱docker是一項技術突破,並且是一次技術革命。
Docker是一個雲開源專案,託管在github,任何人都可以通過 git clone 或者fork參與進來,本身是基於linux的容器技術,採用當時如日中天google新推出的Go語言實現。採用apache 2.0協議開源。
Docker的是一個輕量級的作業系統虛擬化解決方案。 主要目標,用官網的概括來說就是“Build,Ship and Run Any App,Anywhere”:編譯,裝載任何App,在任何地方都可以執行,我們大概理解就是一個容器,實現了對應用的封裝,部署,執行等生命週期管理,只要在glibc的環境下,到處都可以執行。
容器有效的將單個作業系統管理的資源劃分到孤立的組中,以便更好的在孤立的組之間平衡有衝突的資源使用需求。與虛擬化相比,這樣既不需要指令級模擬,也不需要即時編譯。容器可以在核心CPU本地執行指令,而不需要任何專門的解釋機制。此外,也避免了準虛擬化(paravirtualization)和系統呼叫替換中的複雜性。
簡而言之就是,Docker是一個盒子,一個盒子裝一個玩具,無論你丟在哪裡,你給他通電(glibc),他就能執行。你的玩具大就用大盒子,小玩具就用小盒子。
兩個應用之間的環境是環境是完全隔離的,建立通訊機制來互相呼叫。容器的建立和停止都十分快速(秒級),容器自身對資源的需求十分有限,遠比虛擬機器本身佔用的資源少。
• Docker 內部
要理解 Docker 內部構建,需要理解以下三種部件:
Docker 映象 - Docker images
Docker 倉庫 - Docker registeries
Docker 容器 - Docker containers
(1) Docker 映象
Docker 映象是 Docker 容器執行時的只讀模板,每一個映象由一系列的層 (layers) 組成。Docker 使用 UnionFS 來將這些層聯合到單獨的映象中。UnionFS 允許獨立檔案系統中的檔案和資料夾(稱之為分支)被透明覆蓋,形成一個單獨連貫的檔案系統。正因為有了這些層的存在,Docker 是如此的輕量。當你改變了一個 Docker 映象,比如升級到某個程式到新的版本,一個新的層會被建立。因此,不用替換整個原先的映象或者重新建立(在使用虛擬機器的時候你可能會這麼做),只是一個新 的層被新增或升級了。現在你不用重新發布整個映象,只需要升級,層使得分發 Docker 映象變得簡單和快速。
(2) Docker 倉庫
Docker 倉庫用來儲存映象,可以理解為程式碼控制中的程式碼倉庫。同樣的,Docker 倉庫也有公有和私有的概念。公有的 Docker 倉庫名字是 Docker Hub。Docker Hub 提供了龐大的映象集合供使用。這些映象可以是自己建立,或者在別人的映象基礎上建立。Docker 倉庫是 Docker 的分發部分。官方的Docker倉庫地址如下:/file/2019/11/23/20191123054255_41163.jpg Docker 公司維護,上面有數以萬計的映象,使用者可以自由下載和使用
(3)Docker 容器
Docker 容器和資料夾很類似,一個Docker容器包含了所有的某個應用執行所需要的環境。每一個 Docker 容器都是從 Docker 映象建立的。Docker 容器可以執行、開始、停止、移動和刪除。每一個 Docker 容器都是獨立和安全的應用平臺,Docker 容器是 Docker 的執行部分。
二:Mac Docker開發環境搭建官方下載地址誰用誰知道,百度雲:連結:/file/2019/11/23/20191123054255_41164.jpg 密碼:9uly
Docker for Mac一步到位,不需要使用命令進行安裝。安裝完成之後,鯨魚的小圖標出現了。
開啟終端:
註冊Docker hub
/file/2019/11/23/20191123054256_41165.jpg ID用來存放自己的映象.
註冊完成之後,建立自己的Docker倉庫。分為共有和私有,大家根據自己的需要建立即可。
三:Golang Docker部署使用先在本地生成一個映象,在pull到Dockerhub,然後在伺服器push這個映象,執行。
在本地列出已經下載下來的映象,可以使用 docker images 命令。
下面我們開始正式將我們的Go進行Docker化部署。
(1)main.go檔案我們簡單的實現一個伺服器
package mainimport ( "fmt" "net/http")func handler(rw http.ResponseWriter, req *http.Request) { fmt.Fprintf(rw, "hello world, %s", req.URL.Path[1:])}func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)}
監聽8080埠,訪問時返回hello world + 請求引數,功能很簡單。
(2)Dockerfile檔案
Dockerfile 是一個文字檔案,其內包含了一條條的指令(Instruction),每一條指令構建一層,因此每一條指令的內容,就是描述該層應當如何構建。
FROM golangADD . $GOPATH/src/firstdockerWORKDIR $GOPATH/src/firstdocker RUN go install firstdocker ENTRYPOINT /go/bin/firstdocker EXPOSE 8080
• FROM 指定基礎映象
所謂定製映象,那一定是以一個映象為基礎,在其上進行定製。而 FROM 就是指定基礎映象,因此一個 Dockerfile 中 FROM 是必備的指令,並且必須是第一條指令。這裡是指定golang的環境。
• ADD
如果 <源路徑> 為一個 tar 壓縮檔案的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,ADD 指令將會自動解壓縮這個壓縮檔案到 <目標路徑> 去。
在 Docker 官方的最佳實踐文件中要求,儘可能的使用 COPY,因為 COPY 的語義很明確,就是複製檔案而已,而 ADD 則包含了更復雜的功能,其行為也不一定很清晰。最適合使用 ADD 的場合,就是所提及的需要自動解壓縮的場合。
另外需要注意的是,ADD 指令會令映象構建快取失效,從而可能會令映象構建變得比較緩慢。
因此在 COPY 和 ADD 指令中選擇的時候,可以遵循這樣的原則,所有的檔案複製均使用 COPY 指令,僅在需要自動解壓縮的場合使用 ADD。
• WORKDIR 指定工作目錄
格式為WORKDIR <工作目錄路徑>。
使用WORKDIR指令可以來指定工作目錄(或者稱為當前目錄),以後各層的當前目錄就被改為指定的目錄,如該目錄不存在,WORKDIR會幫你建立目錄。
每一個 RUN都是啟動一個容器、執行命令、然後提交儲存層檔案變更。第一層 RUN cd /app 的執行僅僅是當前程序的工作目錄變更,一個記憶體上的變化而已,其結果不會造成任何檔案變更。而到第二層的時候,啟動的是一個全新的容器,跟第一層的容器更完全沒關係,自然不可能繼承前一層構建過程中的記憶體變化。
因此如果需要改變以後各層的工作目錄的位置,那麼應該使用 WORKDIR指令。
• RUN 執行命令
RUN指令是用來執行命令列命令的。由於命令列的強大能力,RUN 指令在定製映象時是最常用的指令之一。其格式有兩種:
shell 格式:RUN <命令>,就像直接在命令列中輸入的命令一樣。剛才寫的 Dockrfile 中的 RUN 指令就是這種格式。
RUN go install firstdocker
exec 格式:RUN ["可執行檔案", "引數1", "引數2"],這更像是函式呼叫中的格式。
既然 RUN 就像 Shell 指令碼一樣可以執行命令,那麼我們是否就可以像 Shell 指令碼一樣把每一層構建需要的命令寫出來,比如這樣:
FROM debian:jessie RUN buildDeps='gcc libc6-dev make' \\• && apt-get update \\• && apt-get install -y $buildDeps \\• && wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \\• && mkdir -p /usr/src/redis \\• && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \\• && make -C /usr/src/redis \\• && make -C /usr/src/redis install \\• && rm -rf /var/lib/apt/lists/* \\• && rm redis.tar.gz \\• && rm -r /usr/src/redis \\• && apt-get purge -y --auto-remove $buildDeps
僅僅使用一個 RUN指令,並使用&&將各個所需命令串聯起來。在撰寫 Dockerfile 的時候,要經常提醒自己,這並不是在寫 Shell 指令碼,而是在定義每一層該如何構建。
並且,這裡為了格式化還進行了換行。Dockerfile 支援 Shell 類的行尾新增 \\的命令換行方式,以及行首#進行註釋的格式。良好的格式,比如換行、縮排、註釋等,會讓維護、排障更為容易,這是一個比較好的習慣。
此外,還可以看到這一組命令的最後添加了清理工作的命令,刪除了為了編譯構建所需要的軟體,清理了所有下載、展開的檔案,並且還清理了 apt 快取檔案。這是很重要的一步,我們之前說過,映象是多層儲存,每一層的東西並不會在下一層被刪除,會一直跟隨著映象。因此映象構建時,一定要確保每一層只新增真正需要新增的東西,任何無關的東西都應該清理掉。
很多人初學 Docker 製作出了很臃腫的映象的原因之一,就是忘記了每一層構建的最後一定要清理掉無關檔案。
• ENTRYPOINT
ENTRYPOINT命令指令指示/go/bin/firestwebapp設定為隨容器啟動
• EXPOSE宣告埠
EXPOSE 指令是宣告執行時容器提供服務埠,這只是一個宣告,在執行時並不會因為這個宣告應用就會開啟這個埠的服務。在 Dockerfile 中寫入這樣的宣告有兩個好處,一個是幫助映象使用者理解這個映象服務的守護埠,以方便配置對映;另一個用處則是在執行時使用隨機埠對映時,也就是 docker run -P時,會自動隨機對映 EXPOSE的埠。
要將 EXPOSE 和在執行時使用 -p <宿主埠>:<容器埠>區分開來。-p,是對映宿主埠和容器埠,換句話說,就是將容器的對應埠服務公開給外界訪問,而 EXPOSE僅僅是宣告容器打算使用什麼埠而已,並不會自動在宿主進行埠對映。
步驟:
(1)開始構建映象
docker build -t="[name]:[tag]" ./docker build -t firstdocker .
(2)檢視映象
docker images docker rmi firstdocker:class. //刪除 名稱:tag docker rmi firstdocker 6712bba50601 //刪除,使用ImageID
(3)執行映象
docker run -v [宿主目錄]:[映象目錄] -ti -p [宿主埠]:[映象埠] 映象名稱:版本
docker run -p 89:8080 --rm firstdocker
-p 80:8080標誌開啟HTTP埠80並將其對映至前面通過EXPOSE命令暴露的8080埠,而—rm標誌則指示Docker在容器已經存在的情況下,先移除已有的容器,然後再建立並啟動新容器。
(4)測試效果
這時候開啟瀏覽器http://localhost,可以看到成功輸出。
(5)將映象上傳
docker login
docker push 註冊使用者名稱/映象名
再去登入自己的dockerHub,就能看到上傳的映象
(6)伺服器拉去映象
docker pull 註冊使用者名稱/映象名
然後執行
docker run -p 80:8080 --rm firstdocker
這個時候只需要在瀏覽器輸入您的ip地址就會有hello world
(7)docker ps //檢視已啟動容器
(8)docker stop 363e265c7e66 //關閉容器
使用上述的方式,上傳至Dockerhub的時候,會出現問題,程式碼修改為下面的即可。
docker build -t zh/firstdocker:test .docker push zh/firstdocker:testdocker pull 註冊使用者名稱/映象名docker run -p 89:8080 --rm firstdocker
其中zh是我的DockerHub的賬戶名。test是tag,用來標識這個映象。
Docker for Mac 版本,那麼所有的docker images 儲存在下面這個檔案裡。
/Users/ZH/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.qcow2
很不幸,截止到今天(2016年11月16日)你還沒有辦法指定images和container的儲存路徑,你只能任由docker吃掉你的磁碟。
下面我們將上傳到伺服器的Docker容器進行雲部署,這樣就可以直接訪問了。
操作步驟如下:
(1)配置好騰訊雲的docker,輸入docker version檢視
(2)docker login 登陸dockerhub,輸入使用者名稱和密碼
(3)docker pull zhuyuqiang/firstdocker:test 從伺服器拉取資料
(4)pull成功之後,使用docker images檢視
(5)輸入下面的命令啟動容器
docker run -p 80:8080 --rm docker.io/zhuyuqiang/firstdocker:test
(6)瀏覽器輸入ip以及埠號測試即可
(7)停止容器
docker stop 8cd24fcf9307
其中8cd24fcf9307為docker的CONTAINER ID
四:騰訊雲配置Docker前提:騰訊雲:CentOS Linux release 7.2.1511 (Core)
(1)使用root使用者登陸騰訊雲,開始安裝docker步驟
(2)安裝配置Docker
# 安裝docker
yum install -y docker
中間會出現各種問題,學會使用goole進行搜尋解決。
[Errno 256] No more mirrors to try 解決方法
輸入下面的命令即可解決問題:
yum clean all yum makecache
# 配置騰訊雲映象加速(官方的龜速)
vim /etc/sysconfig/docker
#新增如下引數:
OPTIONS='--registry-mirror=https://mirror.ccs.tencentyun.com'
#重啟docker服務:
systemctl restart docker
2、製作基礎映象
拉取 centos官方基礎映象\tdocker pull centos \t檢視當前映象\tdocker images [root@VM_0_9_centos /]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEdocker.io/centos latest 1e1148e4cc2c 4 weeks ago 202 MB
執行並進入映象:
docker run -ti docker.io/centos:latest /bin/bash
此時,終端已經進入了映象裡面,現在我們可以根據自己的需求安裝額外的元件,比如我這次需要用到crontab任務計劃服務、程序守護supervisor等,那麼直接在這個終端開始操作:
[root@0d7f7b8769d9 /]# yum install -y epel-release crontabs[root@0d7f7b8769d9 /]# yum install -y python-pip[root@0d7f7b8769d9 /]# pip install --upgrade pip[root@0d7f7b8769d9 /]# pip install supervisor
上面的PS提示符中的 0d7f7b8769d9 就是本次啟動的 CONTAINER ID ,在下面的commit步驟即將用到。 完成必要元件安裝之後,按下 Ctrl +D 退出系統,接著使用 docker commit 命令建立新映象,比如命名為 nginx-proxy-base,版本latest:
docker commit 0d7f7b8769d9 centos/nginx-proxy-base:latest
儲存容器
檢視所有的容器資訊, 能獲取容器的id
docker ps -a
然後執行如下命令[?],儲存映象:
docker commit -m="備註" CONTAINER_ID IMAGE
執行完成後,可以使用 docker images 檢視剛建立的映象:
[root@VM_0_9_centos home]# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEcentos/nginx-proxy-base latest ad1c1ce41689 6 seconds ago 272 MBdocker.io/centos latest 1e1148e4cc2c 4 weeks ago 202 MB
退出映象:exit到此,我們就建立了一個自定義的Docker基礎映象(基礎映象類似一個VM虛擬機器的快照,方便後續步驟都可以從這個基礎上重新制作)
這裡展示的是進入Docker裡面通過手工部署的方式,其實我們還可以通過DockerFile來完成上述所有操作,可以極大的減小Docker映象的體積。
啟動docker
service docker start
設定開機啟動
chkconfig docker on
Docker常用命令:
其中<>闊起來的引數為必選,[]闊起來為可選
docker version 檢視docker的版本號,包括客戶端、服務端、依賴的Go等 docker info 檢視系統(docker)層面資訊,包括管理的images, containers數等 docker search 在docker index中搜索image docker pull 從docker registry server 中下拉image docker push 推送一個image或repository到registry docker push :TAG 同上,指定tag docker inspect 檢視image或container的底層資訊 docker images TODO filter out the intermediate image layers (intermediate image layers 是什麼) docker images -a 列出所有的images docker ps 預設顯示正在執行中的container docker ps -l 顯示最後一次建立的container,包括未執行的 docker ps -a 顯示所有的container,包括未執行的 docker logs 檢視container的日誌,也就是執行命令的一些輸出 docker rm 刪除一個或多個container docker rm `docker ps -a -q` 刪除所有的container docker ps -a -q | xargs docker rm 同上, 刪除所有的container docker rmi 刪除一個或多個image docker start/stop/restart 開啟/停止/重啟container docker start -i 啟動一個container並進入互動模式 docker attach attach一個執行中的container docker run 使用image建立container並執行相應命令,然後停止 docker run -i -t /bin/bash 使用image建立container並進入互動模式, login shell是/bin/bash docker run -i -t -p 將container的埠對映到宿主機的埠 docker commit [repo:tag] 將一個container固化為一個新的image,後面的repo:tag可選 docker build 尋找path路徑下名為的Dockerfile的配置檔案,使用此配置生成新的image docker build -t repo[:tag] 同上,可以指定repo和可選的tag docker build - 使用指定的dockerfile配置檔案,docker以stdin方式獲取內容,使用此配置生成新的image docker port 檢視本地哪個埠對映到container的指定埠,其實用docker ps 也可以看到\tdocker build -t webservice .:表示使用當前目錄下的DockerFile來生成映象,-t引數的值表示映象的tagname,如果DockerFile在當前路徑下則使用.,如果不在當前路徑下則使用相對路徑。\tdocker ps -a: 沒有-a引數表示顯示當前宿主機的正在執行的容器,加上-a表示顯示當前宿主機所有的容器,包括已經退出的容器。\tdocker run -d -p 2222:22 --name base centos:7.1表示根據指定的映象後臺執行容器,容器的名字是base(--name就是指定容器的名字),centos:7.1表示映象的名字,-p引數表示當前宿主機的2222埠對應容器的22埠。-d引數表示(Run container in background and print container ID)\tdocker exec -it base /bin/bash以互動式命令進入base容器並且執行/bin/bash命令\tdocker rmi webservice:刪除webservice映象\tdocker rm base: 刪除base容器,如果base正在執行,則可以使用\tdocker rm -f base進行強行刪除
使用ps -ef | grep docker檢視docker程序。
管理docker服務:
service docker start
service docker stop
service docker restart
啟動配置檔案儲存位置
Ubuntu: /etc/default/docker
CentOS: /etc/sysconfig/docker