『壹』 Docker 1.6.2 的 Client API 不支持stats了嗎
由於 Docker 編譯需要依賴於 Docker Daemon ,所以只能在 64 位的 linux 環境下先安裝 Docker 程序,再從 Github 上克隆 Docker 的代碼進行編譯。 在 Docker 的目錄下執行 make 命令將默認執行 Makefile 中 make binary 指令進行編譯。 ? defaul...
『貳』 如何在 CentOS 7 上安裝 Docker
在編譯docker代碼之前肯定需要研究一下docker的代碼結構以及官方推薦的方式,因為docker是開源的,所以很多第三方開發者參與。那麼官方肯定會給出開發環境搭建的文檔,所以拿到代碼肯定先研究官方的編譯方法。通過文檔和代碼了解到docker官方推薦的是在docker本身的容器裡面搭建環境和編譯,官方給出的是一個基於ubuntu的dockerfile。不過正是這個dockerfile可以清楚的知道需要為了編譯准備哪些依賴環境,為我們後面自己編譯提供了環境搭建的基礎。然後就嘗試了官方的編譯方案,結果各種網路問題導致編譯通不過,當然網上也有相應的解決方案,基本上就是替換一些依賴源(國外的被牆了)。但是就算編譯通過了也只是一個基於ubuntu的二進制文件,只能在ubuntu的相應的系統上運行。我們需要的是一個可以在centos7上運行的二進制文件,關鍵要搭建一個可以持續開發和編譯測試的環境。當然也可以製作一個centos7的dockerfile文件,對照著官方的ubuntu的dockerfile也很簡單。但是這些都是還需要有一個前提,就是需要先安裝一個以前版本的docker來啟動這個環境澀,好處也是杠杠的,可以在任何一台能夠運行docker的系統上進行開發和測試,而且可以進行持續集成。不過對於我們來說能夠編譯出一個穩定運行在centos7上的二進制文件即可,所以就嘗試直接在本地進行編譯,而不是通過docker的容器進行。
經過研究docker的官方編譯腳步,發現本地編譯也很簡單,只需要在docker源碼的目錄下執行如下命令即可:
./hack/make.sh binary
上面這條命令就只會生成docker的二進制文件,不過肯定不會這么順利的,執行這個命令你就會發現錯誤。如果第一次執行報的錯誤應該是找不到相應的go依賴包。那麼現在就開始解決第一個問題,go依賴包。
解決go依賴包最直接的方法就一個一個去github或者其他地方去下載到本地,但是這樣做很麻煩,docker依賴的go語言包很多,然後依賴包可能又依賴其他包。這里有一個簡單實用的辦法,也是go語言管理項目的方便之處。通過go get命令來自動下載,例如發現報錯的是docker某一個目錄下的依賴包,那麼可以如下執行:
go get -v ./src/github.com/docker/docker/...
這條命令執行以後整個docker目錄下源文件依賴的包都會被自動下載。如果發現其他目錄下源文件也報同樣的錯誤,可以按照次方法解決。不過這里需要強調一點,這些下載都是會下載最新的包,如果編譯老的docker肯定會出問題,如果編譯最新的docker代碼肯定不會有問題,因為官方的編譯是這種方式。
上面執行的命令都是建立在go語言環境建立成功的基礎上,我安裝的go遇到是1.3.3版本的,採用源碼方式安裝。安裝在/export/servers/go下面,然後所有的go語言工程源碼目錄放在/export/servers/gopath。然後配置環境變數在用戶的根目錄下的.bashrc文件裡面如下:
export GOPATH=/export/servers/gopath
export GOROOT=/export/servers/go
export GOARCH=amd64
export GOOS=linux
然後docker的代碼目錄如下:/export/servers/gopath/src/github.com/docker/docker。這樣才能在gopath下面進行依賴包的下載。通過上面的方法把所有依賴包下載完以後就可以進行編譯了。
在繼續編譯的過程中還會遇到缺少c語言依賴包缺少的問題,主要有三個,(1)sqlite3;(2)device-mapper;(3)btrfs.
第一個sqlite3可以使用如下命令安裝依賴:yum install sqlite-devel.x86_64
第二個在官方的dockerfile文件裡面有解決方案,執行如下命令:
git clone --no-checkout https://git.fedorahosted.org/git/lvm2.git /usr/local/lvm2 && cd /usr/local/lvm2 && git checkout -q v2_02_103
cd /usr/local/lvm2 && ./configure --enable-static_link && make device-mapper && make install_device-mapper
第三個btrfs使用如下安裝依賴: yum install btrfs-progs。
這些依賴都解決了就繼續編譯,這個時候可能會出現ld連接錯誤,提示找不到庫。因為docker編譯的方式完全是static,所以所有依賴的庫必須還要有相應的靜態庫(.a),而不是動態庫(.so)。剛才通過yum install sqlite-devel.x86_64安裝了sqlite3的依賴,但是最後發現裡面沒有靜態庫,所以編譯ld的時候出錯了。我的解決辦法就是重新到sqlite3的官方網站下載了源碼包,然後編譯安裝即可。
編譯完成以後,就會在docker源碼目錄下的bundles/1.3.1/binary/目錄有如下文件:
docker docker-1.3.1 docker-1.3.1.md5 docker-1.3.1.sha256
docker-1.3.1這個文件就是我們需要的二進制文件了,docker是一個軟連接到docker-1.3.1的文件。
到此就成功完成編譯了,以後修改了代碼重新支持編譯腳步即可:
./hack/make.sh binary
『叄』 carla-docker中編譯carla ue4血淚史
carla官方之前推薦的在carla中導入新地圖的方式是在ubuntu下使用UE4加carla插件進行地圖加工然後導出,但是比較麻煩,然後官方在2020年4月份將之前的方法歸類為不推薦方式。推薦在docker下使用carla提供的腳本便捷生產carla地圖。然後就開始了入坑之旅。
carla官方給出的教程 在此 .
1.安裝docker-ce
參考此 教程
2.安裝python 3.6或著更高版本。(ubuntu 18.04默認為python3.6 可跳過此步驟)
3.安裝 ue4-docker
4.使用ue4-docker配置ubuntu防火牆。
多說幾句,在進行此步驟後,明明已經安裝了 ue4-docker,但是運行時提示 ue4-docker不存在或者未安裝,最後通過將 ue4-docker文件拷貝到bin文件夾下解決。具體參考 這里
5.編譯docker鏡像
重要 注意將4.22.2更改為4.24.3
此步耗費時間較長,因為要安裝差不多10個G的UE依賴。
此步驟是具體如下編譯編譯carla所需依賴的鏡像,聽起來比較拗口,但就是這樣。
創建真正的Carla鏡像。
『肆』 一文教您如何通過 Docker 快速搭建各種測試環境
目錄
一、鏡像加速
Docker 默認是從官方鏡像地址 Docker Hub 下下載鏡像,由於伺服器在國外的緣故,導致經常下載速度非常慢。為了提升鏡像的下載速度,我們可以手動配置國內鏡像加速器,讓下載速度飈起來。
國內的鏡像加速器選項較多,如:阿里雲,DaoCloud 等。
本文主要說說如何配置阿里雲的鏡像加速器。
2.1 登錄阿里雲獲取加速信息
https://dev.aliyun.com/
2.2 配置 Docker
2.2.1 確定 Docker Client 版本
在配置之前,首先需要 確定 Docker Client 的版本,推薦是 1.10.0+ :
2.2.2 配置鏡像加速器
PS: 這里以 CentOS 系統為例,如果你是別的系統,可以參考阿里雲配置加速器官方文檔。
通過修改 daemon 配置文件 /etc/docker/daemon.json 來使用加速器:
執行下面命令:
2.3 驗證一下速度
以下載 mongodb 為例,看下速度:
配置了加速器過後,速度終於飈起來了。
二、快速安裝&搭建 Mysql 環境
本節中,我們將學習如何通過 Docker 快速安裝與搭建 Mysql 環境。
2.1 下載 Mysql 鏡像
這里以 Mysql 5.7 為例:
下載完成後,通過 docker images 檢查一下鏡像是否下載成功:
2.2 先以最簡單方式啟動
先以簡單的方式啟動:
命令執行完成後,你也可以通過 docker ps 命令來確認下容器是否啟動成功。若成功,我們需要將容器中的目錄文件復制到宿主機中,分別包括:
完成這一切後,讓我們將剛剛運行的容器刪除掉。
PS: mysql 是我們運行容器時,指定的名稱,當然,你也可以先執行 docker ps , 通過容器 ID 來刪除。
2.3 正式運行 Mysql 容器
接下來,正式運行 Mysql 容器:
其他不變,額外添加了兩個掛載子命令:
執行命令完成後,查看下容器是否啟動:
可以看到,容器運行成功
2.4 通過 Mysql 客戶端連接一下試試
通過 MySQL 客戶端連接剛剛創建的 mysql, 看看能否連接成功:
連接成功了!
三、快速安裝&搭建 Redis 環境
本節中,我們將學習如何利用 Docker 安裝&搭建 Redis 環境。
3.1 下載 Redis 鏡像
首先拉取 Redis 鏡像, 這里我選擇的是 redis:alpine 輕量級鏡像版本:
下載完成後,通過 docker images 確認鏡像是否已經下載到本地:
3.2 運行 Redis 容器
命令說明:
命令運行完成後,查看容器是否啟動成功:
可以看到 redis 容器已經啟動成功了!
3.3 連接剛剛創建好的容器
執行如下命令,連接 redis:
四、快速安裝&搭建 MongDB 環境
本節中,我們將學習如何通過 Docker 快速安裝與搭建 MongoDB 環境。
4.1 下載 MongoDB 鏡像
這里以 mongo 4 版本為例,下載鏡像:
下載完成後,確認一下鏡像是否下載成功:
4.2 運行 MongoDB 鏡像
下載成功後,運行 mongoDB 鏡像:
執行命令完成後,查看下容器是否啟動:
4.3 添加管理員賬號
執行命令:
然後,創建一個擁有最高許可權 root 賬號:
創建成功後,你會看到 Successfully added user :
4.4 用新創建的 root 賬戶連接,測試一下
連接成功後,我們可以執行相關 sql:
顯示所有的資料庫:
使用某個資料庫:
輸入命令 exit ,退出連接!
五、快速安裝&搭建 Elasticsearch 環境
本節中,我們將學習如何通過 Docker 快速安裝與搭建 Elasticsearch 環境。
5.1 下載 Elasticsearch 鏡像
這里以 Elasticsearch 6.5.0 為快速安裝&搭建 Elasticsearch 環境例:
下載完成後,通過 docker images 檢查一下鏡像是否下載成功:
5.2 先簡單運行 Elasticsearch 鏡像
下載成功後,簡單運行 Elasticsearch 鏡像:
命令執行完成後,你也可以通過 docker ps 命令來確認下容器是否啟動成功。
可以看到 es 容器運行成功了,接下來,進入容器中:
安裝 analysis-ik 中文分詞插件:
PS: es 從 v5.5.1 版本開始支持自帶的 es 插件命令來安裝,如果你安裝的版本不是 6.5.0,需要將命令中的版本號修改一下,具體參考 https://github.com/medcl/elasticsearch-analysis-ik
安裝成功後,退出容器:
刪除剛剛運行的容器:
PS: 當然了,你也可以通過容器的 ID 來刪除。
5.3 復制相關文件
5.4 修改 es 相關配置
進入我們剛剛指定的 config 配置目錄,修改 jvm.options 文件:
PS: 因為小哈測試伺服器就 2G 內存,這里我改成了 JVM 內存佔用 300m, 如果你的內存夠用,可不用改。
修改 elasticsearch.yml 文件, 添加如下配置:
解釋一下添加的配置,設置節點為 master 節點,並允許跨域訪問,以便後面使用 head 插件圖形化界面訪問。
5.5 運行 Elasticsearch 容器
這次,我們額外添加了相關掛載命令:
5.6 測試一下,瞅瞅 es 是否能夠正常訪問
測試一下,看 es 是否啟動成功:
OK, 到此 es 的單節點環境就搭建好了!
歡迎工作一到五年的Java工程師朋友們加入Java程序員開發: 721575865
群內提供免費的Java架構學習資料(裡面有高可用、高並發、高性能及分布式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間「來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!
『伍』 【docker】docker的容器創建與管理過程
# yum -y install docker docker-ce-cli containerd.io
# rpm -qa | grep container
# rpm -qa | grep docker
# rpm -ql docker-ce-cli | grep bin
# rpm -ql docker-ce | grep bin
# rpm -ql containerd.io | grep bin
# systemctl status docker
# systemctl status containerd
/var/run/docker.sock
/run/containerd/containerd.sock
/usr/bin/docker 和 /usr/bin/dockerd 就是命令行客戶端和daemon
dcocker的架構是 C/S 模式
docker-containerd
docker-containerd-ctr
docker-containerd-shim
docker-init
docker-proxy
docker-runc
其實最簡單的方式,就是加個命令行參數 --help 看看他們的簡介。
可以看出來,docker-init, docker-containerd-shim 和 docker-proxy 沒有在幫助里告訴我們是干什麼的,其他的都有:
docker-containerd: 高性能容器運行時
docker-containerd-ctr: docker-containerd 的命令行客戶端
docker-runc: 運行容器的命令行工具
如果去搜索一番,就會發現:docker-containerd 就是 containerd ,而 docker-runc 就是 runc 。
containerd是真正管控容器的daemon,執行容器的時候用的是runc。
為什麼 要分的七零八散呢?
我估計其中主要的原因是防止docker壟斷,因此把容器標准獨立出來,就有了 runtime-spec ,然後有了 runc ,然後有了 containerd (此處發展歷史沒有考究,並不關心)。
可以看出來,docker本身其實已經被剝離干凈了,只剩下docker自身的一些特色功能了,真正容器的管控都在containerd里實現。
所以接下來介紹的順序是 runc, containerd, shim, docker-init, docker-proxy。
runc是標准化的產物,為了防止一家商業公司主導容器化標准,因此又了open containers組織,因此,創建容器,其實最終通過runc就可以了。
dockerd 有個子進程,是 containerd,然後 containerd 有子進程。
從 官方倉庫 的描述可以看出來,其實 containerd 就包含了我們常用的 docker 的命令:
增刪查改容器
增刪查改鏡像
也就是說,如果我們要對容器進行操控,直接使用 containerd 其實就夠了。
說明: 如果沒有單獨起一個containerd,而是使用了 docker-containerd,通過 ps aux | grep docker 發現它使用了 /var/run/docker/containerd/containerd.toml 這個配置文件,而監聽路徑就寫在裡面。
shim的翻譯是墊片,就是修自行車的時候,用來夾在螺絲和螺母之間的小鐵片。
關於shim本身,網上介紹的文章很少,但是作者在 Google Groups 里有解釋到shim的作用:
https://groups.google.com/forum/#!topic/docker-dev/zaZFlvIx1_k
1. 允許runc在創建&運行容器之後退出
2. 用shim作為容器的父進程,而不是直接用containerd作為容器的父進程,是為了防止這種情況:當containerd掛掉的時候,shim還在,因此可以保證容器打開的文件描述符不會被關掉
3. 依靠shim來收集&報告容器的退出狀態,這樣就不需要containerd來wait子進程
因此,使用shim的主要作用,就是 將containerd和真實的容器(里的進程)解耦 ,這是第二點和第三點所描述的。
而第一點,為什麼要允許runc退出呢?
因為,Go編譯出來的二進制文件,默認是靜態鏈接,因此,如果一個機器上起N個容器,那麼就會佔用M*N的內存,其中M是一個runc所消耗的內存。 但是出於上面描述的原因又不想直接讓containerd來做容器的父進程,因此,就需要一個比runc占內存更小的東西來作父進程,也就是shim。但實際上, shim仍然比較占內存( 參考這里 )。
我們都知道UNIX系統中,1號進程是init進程,也是所有孤兒進程的父進程。
而使用docker時,如果不加 --init 參數,容器中的1號進程 就是所給的ENTRYPOINT。
而加上 --init 之後,1號進程就會是 tini 。
在entrypoint.sh中使用Tini的優勢是什麼?
https://zhuanlan.hu.com/p/59796137
用來做容器和宿主機之間的埠映射,其底層是使用iptables來完成的。
The docker-proxy
https://windsock.io/the-docker-proxy
docker本身而言包括了,docker client和dockerd(docker daemon),dockerd本身實屬是對容器相關操作的api的最上層封裝,
直接面向操作用戶。
dockerd
dockerd本身實屬是對容器相關操作的api的最上層封裝,直接面向操作用戶。
containerd
dockerd實際真實調用的還是 containerd的api介面(rpc方式實現 ),containerd是dockerd和runc之間的一個中間交流組件。
containerd-shim
containerd-shim是一個運行的容器的真實墊片載體,每啟動一個容器都會起一個新的docker-shim進程。
他直接通過指定的三個參數:容器id,boundle目錄(containerd的對應某個容器生成的目錄,一般位於:/var/run/docker/libcontainerd/containerID),運行二進制(默認為runc)來調用runc的api創建一個容器(比如創建容器:最後拼裝的命令如下:runc create )
runc
runc是一個命令行工具端,根據oci(開放容器組織)的標准來創建和運行容器。
1. docker 與 dockerd 通過/var/run/docker.sock 通訊
2. dockerd通過 grpc 與containerd模塊通信,dockerd由libcontainerd負責和containerd進行交換,dockerd與containerd通信socket文件為 /run/containerd/containerd.sock
3. containerd在dockerd啟動時 被啟動 ,然後containerd啟動grpc請求監聽,containerd處理grpc請求,根據請求做相應動作
4. 若是start或是exec容器,containerd拉起一個 container-shim ,並進行相應的操作
5. container-shim拉起後,start/exec/create拉起runC進程,通過exit、control文件和 containerd 通信,通過父子進程關系和SIGCHLD監控容器中進程狀態
6. 在整個容器生命周期中,containerd通過epoll監控容器文件,監控容器事件
Docker組件介紹(一):runc和containerd
https://jiajunhuang.com/articles/2018_12_24-docker_components_part2.md.html
Docker組件介紹(二):shim, docker-init和docker-proxy
https://jiajunhuang.com/articles/2018_12_24-docker_components_part2.md.html
關於docker啟動一個容器後進程
https://www.jianshu.com/p/caad2176186f
『陸』 M1使用docker部署rocketmq單機版
以下為本人部署時的環境介紹
由於M1是arm架構,docker hub中的rocketmq 和 rocketmq-console-ng控制台都需要自己編譯鏡像
我已編譯好一版,可以直接拿來用[candice0630/rocketmq-console-ng:2.0]
!!重點強調:正常情況下只要執行(mvn clean package -Dmaven.test.skip=true docker:build)命令就可以編譯docker鏡像,但是我失敗了😭 jar包編譯成功,但是打docker鏡像報錯,所以我分別執行兩步驟!!
由於咱們是docker構建服務,我在使用第三方rocketmq-client包創建生產者時總是使用docker分配的內網ip進行連接,因連接不通,所以我們需要修改broker配置,使其用本地ip進行連接。具體配置如下:
使用docker-compose執行第三部配置好的yml文件
eg: docker-compose -f rocketmq.yml up -d
然後我就成功啦!!
再訪問localhost:19876 rocketmq控制台進行簡單測試
rocketmq目前本人還在學習階段,對docker了解也較淺,所以目前先簡單介紹學習rocketmq的第一步 本地部署。希望此篇文章可以讓小夥伴兒們避免一些坑😜
『柒』 Docker是什麼它比虛擬機強在哪裡
Docker是一個開源的應用容器引擎,可以讓開發者將自身的應用或者軟體移植到鏡像中,然後發布到任何一個Windows機器或者Linux機器上,當然Docker也可以實現虛擬化。而一個完整的Docker是由:Docker Client客戶端,Docker Daemon 守護進程,Docker Image 鏡像和Docker Container 容器來組成的。容器是完全採用沙箱機制,相互之間不會有任何介面。
而Docker比虛擬機強大的地方在於:
第一:啟動時間:Docker容器是秒級啟動的,而虛擬機時分鍾級啟動,在啟動速度方面,Docker就能夠完美地碾壓了虛擬機。
第二:佔用空間和性能:在佔用空間和性能方面,Docker容器鏡像比虛擬機要小得多且性能要比虛擬機更強。
第三:使用要求:虛擬機是基於硬體的虛擬化,其CPU也要有支持虛擬化的支持,Docker共享宿主機內核,可運行在主流的Linux,不用考慮CPU是否支持虛擬化技術。
『捌』 docker client is out of sync
Docker的Client端
1、 DockerCli結構體封裝前面說到會生成一個DockerCli struct結構體對象,解析文件在在這個路徑下:/cli/command/cli.godocker Client解析了命令行之後,會通過其中的client.APIClient和docker Server端進行通信,其結構體定義函數和實現類函數的定義。
2、docker 鏡像我們以docker image ls為例子,研究docker的Client端是怎麼把信息發給Server端的。
『玖』 docker ubuntu鏡像能不能安裝
docker ubuntu鏡像能安裝
docker安裝
對於Docker的安裝在官網上針對不同的操作系統分別進行了描述,Ubuntu上安裝Docker,對於ubuntu操作系統來說必須是64位的,因為Docker的官網上只是提供了64位的docker,如果需要32位的docker則需要下載源碼進行編譯,這里有篇文章介紹了Docker源碼如何進行編譯成32位,編譯32位的Docker。但是對於我使用的Ubuntu來說正好是32位的。通過下面的兩條命令可以看出操作系統的位數和Linux的內核版本。
root@ubuntu:/tmp#uname -a
Linux e529c1b7772a 3.13.0-12-generic #32-Ubuntu SMP Fri Feb 21 17:44:24 UTC 2014 i686 i686 i686 GNU/Linux
root@ubuntu:/tmp#file /sbin/init
/sbin/init: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=, stripped
如果想在32為的Ubuntu操作系統上運行Docker的話,就必須安裝32位的Docker。在Ubuntu中提供docker1.01-32位的deb包,可以直接點擊「docer1.01-32位deb包」跳轉到下載頁面。下載完成後,直接使用dpkg –i進行安裝。
dpkg -i docker.io_1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1_i386.deb
Selecting previously unselected package docker.io.
(Reading database ... 150021 files and directories currently installed.)
Preparing to unpack docker.io_1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1_i386.deb ...
Unpacking docker.io (1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1) ...
Setting up docker.io (1.0.1~dfsg1-0ubuntu1~ubuntu0.14.04.1) ...
docker.io start/running, process 10456
Processing triggers for ureadahead (0.100.0-16) ...
Processing triggers for man-db (2.6.6-1) ...
也可以參考下面的這篇文章《Docker 1.0.1 已經可以在 Ubuntu 14.04 LTS 上測試了!》進行安裝。安裝完成後,可以使用下面的命令確定安裝的版本和基本的信息。由於docker使用go語言進行編寫的,所以要依賴於GO的編譯工具和庫文件。
oot@ubuntu:/tmp# docker version
Client version: 1.0.1
Client API version: 1.12
Go version (client): go1.2.1
Git commit (client): 990021a
Server version: 1.0.1
Server API version: 1.12
Go version (server): go1.2.1
Git commit (server): 990021a
root@ubuntu:/tmp# docker info
Containers: 1
Images: 7
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Dirs: 10
Execution Driver: native-0.2
Kernel Version: 3.13.0-12-generic
WARNING: No swap limit support
官方安裝方式docker pull imagename從docker的索引中心下載,imagename是鏡像名稱,例如docker pull ubuntu就是下載base ubuntu並且tag是latest。
root@ubuntu:/# docker pull ubuntu:14.04
Pulling repository ubuntu
c4ff7513909d: Download complete
511136ea3c5a: Download complete
1c9383292a8f: Download complete
9942dd43ff21: Download complete
d92c3c92fa73: Download complete
0ea0d582fd90: Download complete
cc58e55aa5a5: Download complete
root@ubuntu:~/Downloads# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04 c1b5399bd2ee 8 minutes ago 205.3 MB
learn/tutorial latest 8dbd9e392a96 17 months ago 128 MB
root@ubuntu:/# docker run -i -t ubuntu /bin/bash
2014/09/04 13:04:28 exec format error
docker run -i -t learn/tutorial /bin/bash
2014/09/04 14:45:13 exec format error
PS:在安裝完成Dokcer後,使用Pull命令sudo docker pull ubuntu:14.04從鏡像倉庫獲取ubuntu的鏡像後,然後使用run命令docker run -i -t ubuntu /bin/bash直接運行該鏡像時,會出現下面的錯誤信息,後來我又嘗試著使用官方演示使用的learn/tutorial鏡像,還是出現同樣的問題,現在懷疑可能是由於我安裝的DOcker是32位的,而Image是64位的不匹配造成的。前面說過Docker默認提供的都是64位,其中提供的Image自然也都是64位,所以會出現下面的錯誤信息。在Docker Hub Registry里的大多數鏡像都是64位。這里有一個關於該錯誤的討論帖「Ddocker.io: Docker should recommend
linux-image-amd64 」。所以,如果想在32位的Docker基礎上運行Ubuntu的Image那要求Ubuntu的image也必須是32位。這就需要製作32位Ubuntu的Image。這里有一個官方提供的可用的Ubuntu image的列表,Ubuntu Image tag。
『拾』 超值一篇分享,Docker:從入門到實戰過程全記錄
作者 | 天元浪子
來源 | CSDN博客
想要真正理解Docker,就不得不從虛擬化技術的發展歷程說起。普遍認為虛擬化技術經歷了物理機時代、虛擬機時代,目前已經進入到了容器化時代。可以說,Docker是虛擬化技術不斷發展的必然結果。
那麼,什麼是容器呢?容器和虛擬機有什麼不同?Docker和容器又是什麼關系呢?搞明白這幾個問題,Docker的概念就清晰了。
1.1 虛擬機和容器
藉助於VMWare等軟體,可以在一台計算機上創建多個虛擬機,每個虛擬機都擁有獨立的操作系統,可以各自獨立的運行程序。這種分身術雖然隔離度高(操作系統級),使用方便(類似物理機),但佔用存儲資源多(GB級)、啟動速度慢(分鍾級)的缺點也是顯而易見的。
相較於虛擬機,容器(Container)是一種輕量型的虛擬化技術,它虛擬的是最簡運行環境(類似於沙盒)而非操作系統,啟動速度快(秒級)、佔用存儲資源少(KB級或MB級),容器間隔離度為進程級。在一台計算機上可以運行上千個容器,這是容器技術對虛擬機的碾壓式優勢。
1.2 容器、鏡像和Docker
Docker是一個開源的應用容器引擎,可以創建容器以及基於容器運行的程序。Docker可以讓開發者打包他們的應用和依賴包到一個輕量級、可移植的容器中,然後發布到任何流行的Linux機器上,也可以實現虛擬化。
聽起來很簡單,但是在Docker和容器之間,還隱藏著一個鏡像的概念,令初學者頗感困惑。本質上,Docker鏡像是一個特殊的文件系統,它提供容器運行時所需的程序、庫、資源、配置等文件。Docker鏡像類似於一個py文件,它需要Docker的運行時(類似於Python解釋器)運行。鏡像被運行時,即創建了一個鏡像的實例,一個實例就是一個容器。
1.3 Docker 和 k8s
作為容器引擎,Docker為容器化的應用程序提供了開放的標准,使得開發者可以用管理應用程序的方式來管理基礎架構,實現快速交付、測試和部署代碼。隨著容器的大量使用,又產生了如何協調、調度和管理容器的問題,Docker的容器編排應運而生。
k8s是Google開源的一個容器編排引擎,它支持自動化部署、大規模可伸縮、應用容器化管理,是一個開源的,用於管理雲平台中多個主機上的容器化的應用,k8s的目標是讓部署容器化的應用簡單並且高效,k8s提供了應用部署、規劃、更新、維護的一種機制。
Docker和k8sr都是以containerd(容器化標准)作為運行時,因此使用Docker創建的鏡像完全可以在k8s中無障礙的使用。
2.1 在ubuntu中安裝
在linux系統中安裝Docker非常簡單,官方為我們提供了一鍵安裝腳本。這個方法也適用於Debian或CentOS等發行版。
安裝過程如果出現超時,不要灰心,多試幾次,總會成功的。安裝完成後,Docker只能被root用戶使用,可以使用下面的命令取消許可權限制:
然後,重啟docker服務:
最後,關閉當前的命令行,重新打開新的命令行就可以了。
順便提一下,如果在CentOS下安裝,可能會出現一堆類似於下面的錯誤:
這是由於docker和Podman沖突造成的,需要先卸載Podman:
2.2 在Win10中安裝
Docker的運行,依賴linux的環境,官方提供了Docker Desktop for Windows,但是它需要安裝Hyper-V,Hyper-V是微軟開發的虛擬機,類似於 VMWare 或 VirtualBox,僅適用於 Windows 10。這個虛擬機一旦啟用,QEMU、VirtualBox 或 VMWare Workstation 15 及以下版本將無法使用!如果你必須在電腦上使用其他虛擬機(例如開發 Android 應用必須使用的模擬器),請不要使用 Hyper-V!
我的電腦是win10家庭版,不能直接安裝hyper-v,需要將下面的命令保存到cmd文件中:
然後在cmd文件上點擊右鍵,選擇使用管理員運行。執行完畢後會重啟,在重啟的過程中進行安裝。
2.3 Hello world
docker服務啟動的情況下,運行下面的命令:
此命令的含義是:
第一次運行時,因為本地沒有ubuntu:20.04鏡像,docker會自動從鏡像伺服器下載。下載過程可能需要多試幾次,只要成功一次,以後執行就不再需要下載了。
docker官方還提供了一個hello-world鏡像,可以直接運行:
此命令省略了鏡像版本和運行參數,docker使用latest作為版本,即最新版本。
從hello world的例子中,也可以體驗到,docker實例的運行是非常快的。
docker官方的鏡像庫比較慢,在進行鏡像操作之前,需要將鏡像源設置為國內的站點。
新建文件/etc/docker/daemon.json,輸入如下內容:
然後重啟docker的服務:
3.1 列出本地所有鏡像
執行命令 docker images 可以查看
當前我本地只有剛才安裝的兩個鏡像。
3.2 從鏡像庫中查找鏡像
執行命令 docker search 鏡像名稱可以從docker鏡像庫中查找鏡像。
最好選擇官方(OFFICIAL)的鏡像,這樣的鏡像最穩定一些。
3.3 下載新的鏡像
執行命令docker pull 鏡像名稱:版本號即可下載新的鏡像。
鏡像下載後,就可以使用鏡像來創建容器了。
4.1 啟動容器
執行命令docker run即可啟動容器,也就是創建某個鏡像的實例。docker run命令非常復雜,可以先執行一個docker run --help來查看幫助:
比如我們要執行python的shell,需要添加-it參數,即:docker run -it python:3.8
4.2 將宿主機的文件掛載到容器
docker容器與宿主機是隔離的,要想讓容器內的程序能訪問宿主機上的文件,需要通過-v參數將宿主機的文件掛載到容器中。
比如我們在宿主機上有一個hello.py,可以列印hello,想要在python容器中執行,就需要進行掛載。-v後還需要接兩個參數,分別是宿主機的目錄和容器內的目錄,兩者使用:分隔,路徑必須都是絕對路徑。
我的hello.py保存在主目錄的/docker_test目錄中,將這個目錄掛載到容器的/docker_test目錄,然後在容器內執行python /docker_test/hello.py:
4.3 容器的埠映射
我們修改一下hello.py,創建一個socket服務端,並監聽5000埠,當有客戶端連接時,列印客戶端的地址,先客戶端發送hello,然後關閉連接:
在容器內執行:
接下來,嘗試用telnet命令連接,結果卻是失敗的。原因是,127.0.0.1是宿主機的ip地址,5000是容器的埠,這與我們的習慣稍微有些不同。事實上,docker的容器是非常輕量的,它並沒有自己的網路,要想訪問容器的埠,需要進行埠映射,將容器的某埠映射到宿主機的埠,客戶端連接時,只要與宿主機的埠進行連接就可以了。
需要注意的是,上面的代碼創建的伺服器,無論如何也不可能被客戶端連接,因為代碼中綁定了127.0.0.1的ip,在容器中運行時,需要綁定所有ip,即0.0.0.0。
然後,再使用-p參數,-p還需要三個參數,即宿主機的ip地址、宿主機的埠、容器的埠,三者之間使用:分隔。一般的,可以將宿主機的ip地址省略,只寫宿主機的埠:容器的埠即可。
這樣,就將容器的5000埠映射到了宿主機的5001埠,使用:
即可與容器中的伺服器進行連接。
4.4 容器管理
上面的服務運行之後,可以使用docker ps命令,查看運行中的容器:
顯示的內容有下面幾列:
要想結束容器,可以使用docker kill 容器ID命令。
一般而言,當我們的程序開發完成後,會連同程序文件與運行環境一起製作成一個新的鏡像。
要製作鏡像,需要編寫Dockerfile。DockeFile由多個命令組成,常用的命令有:
注意,Docker鏡像中有一個層的概念,每執行一個RUN命令,就會創建一個層,層過多會導致鏡像文件體積增大。盡量在RUN命令中使用&&連接多條shell命令,減少RUN命令的個數,可以有效減小鏡像文件的體積。
5.1 自製顯示文本文件內容鏡像
編寫cat.py,接收一個文件名,由python讀取文件並顯示文件的內容:
這個例子比較簡單,縮寫Dockerfile如下:
這個Dockerfile的含義是:
需要說明的是,ENTRYPOINT有兩種寫法:
這里採用第二種寫法,是因為我們要在外部給容器傳遞參數。執行命令編譯Docker鏡像:
這個命令中,-t的含義是目標,即生成的鏡像名為hello,版本號為1.0,別忘了最後那個.,這叫到上下文路徑,是指 docker 在構建鏡像,有時候想要使用到本機的文件(比如復制),docker build 命令得知這個路徑後,會將路徑下的所有內容打包。
這樣,我們的第一個鏡像就製作完成了,使用下面的命令執行它:
即可看到~/docker_test/cat/files/test.txt的內容。
5.2 自製web伺服器鏡像
我們使用tornado開發一個網站,而python的官方鏡像是沒有tornado庫的,這就需要在製作鏡像時進行安裝。
測試的ws.py如下:
編寫Dockerfile文件如下:
在此我們驗證一下CMD與ENTRYPOINT的區別。在Dockerfile所在有目錄下執行如下命令:
執行完成後,再使用docker images使用就可以看到生成的鏡像了,然後使用下面的命令運行:
在瀏覽器中輸入宿主機的ip和8000埠,就可以看到頁面了。
在這個例子中,我使用的運行命令是CMD,如果在docker run中指定的其他的命令,此命令就不會被執行,如:
此時,容器中被執行的是python命令,而不是我們的服務。在更多情況下,我們希望在docker run命令中為我們的服務傳參,而不是覆蓋執行命令,那麼,我們應該使用ENTRYPOINT而不是CMD:
上面這種寫法,是不支持傳遞參數的,ENTRYPOINT和CMD還支持另一種寫法:
使用這種寫法,docker run命令中的參數才可以傳遞給hello.py:
這個命令中,--port=9000被作為參數傳遞到hello.py中,因此容器內的埠就成了9000。
在生產環境中運行時,不會使用-it選項,而是使用-d選項,讓容器在後台運行:
這種方式下,即使當前的控制台被關閉,該容器也不會停止。
5.3 自製apscheler服務鏡像
接下來,製作一個使用apscheler編寫的服務鏡像,代碼如下:
Dockerfile也是信手拈來:
生成鏡像:
應該可以運行了,文件復制需要兩個目錄,在運行時,可以使用兩次-v來掛載不同的目錄:
前面用到的官方python鏡像大小足足882MB,在這個基礎上,再安裝用到的第三方庫,添加項目需要的圖片等資源,大小很容易就超過1個G,這么大的鏡像,網路傳給客戶非常的不方便,因此,減小鏡像的體積是非常必要的工作。
docker hub上有個一python:3.8-alpine鏡像,大小隻有44.5MB。之所以小,是因為alpine是一個採用了busybox架構的操作系統,一般用於嵌入式應用。我嘗試使用這個鏡像,發現安裝一般的庫還好,但如果想安裝numpy等就會困難重重,甚至網上都找不到解決方案。
還是很回到基本的路線上來,主流的操作系統鏡像,ubuntu的大小為72.9MB,centos的大小為209MB——這也算是我更喜歡使用ubuntu的一個重要原因吧!使用ubuntu作為基礎鏡像,安裝python後的大小為139MB,再安裝pip後的大小一下子上升到了407MB,要是再安裝點其他東西,很容易就趕上或超過python官方鏡像的大小了。
看來,尋常路線是很難壓縮鏡像文件體積了。幸好,還有一條曲線救國的路可走,這就是多階段構建法。
多階段構建的思想其實很簡單,先構建一個大而全的鏡像,然後只把鏡像中有用的部分拿出來,放在一個新的鏡像里。在我們的場景下,pip只在構建鏡像的過程中需要,而對運行我們的程序卻一點用處也沒有。我們只需要安裝pip,再用pip安裝第三方庫,然後將第三方庫從這個鏡像中復制到一個只有python,沒有pip的鏡像中,這樣,pip佔用的268MB空間就可以被節省出來了。
1、在ubuntu鏡像的基礎上安裝python:
然後運行:
這樣,就生成了python:3.8-ubuntu鏡像。
2、在python:3.8-ubuntu的基礎上安裝pip:
然後運行:
這樣,就生成了python:3.8-ubuntu-pip鏡像。
3、多階段構建目標鏡像:
這個dockerfile需要解釋一下了,因為它有兩個FROM命令。
第一個是以python:3.8-ubuntu-pip鏡像為基礎,安裝numpy,當然,在實際應用中,把所有用到的第三方庫出寫在這里。
第二個FROM是以FROM python:3.8-ubuntu鏡像為基礎,將第三方庫統統復制過來,COPY命令後的–from=0的意思是從第0階段進行復制。實際應用中再從上下文中復製程序代碼,添加需要的ENTRYPOINT等。
最後,再運行:
這然,用於我們項目的鏡像就做好了。比使用官方python鏡像構建的版本,小了大約750MB。
到此,我們的鏡像已經製作好了,可是,鏡像文件在哪,如何在生產環境下運行呢?
剛才使用docker images命令時,已經看到了生成的鏡像:
我們可以使用docker save命令將鏡像保存到指定的文件中,保存的文件是一個.tar格式的壓縮文件:
將hello.tar復制到生產環境的機器上,然後執行導入命令:
就可以使用了。