當前位置:編程學習大全網 - 編程語言 - Dockerfile程序員

Dockerfile程序員

作者|天元浪子

來源| CSDN博客

要想真正了解Docker,還得從虛擬化技術的發展說起。壹般認為,虛擬化技術經歷了物理機和虛擬機時代,現在已經進入容器化時代。可以說Docker是虛擬化技術不斷發展的必然結果。

那麽,什麽是容器呢?容器和虛擬機有什麽區別?Docker和container是什麽關系?理解了這些問題,Docker的概念就清楚了。

1.1個虛擬機和容器

借助VMWare等軟件,可以在壹臺計算機上創建多個虛擬機,每個虛擬機都有獨立的操作系統,可以獨立運行程序。雖然這種分離技術具有高度隔離性(操作系統級)和易用性(類似於物理計算機),但其缺點也很明顯,比如占用存儲資源多(GB級),啟動速度慢(分鐘級)。

與虛擬機相比,容器是壹種輕量級的虛擬化技術,它將最簡單的運行環境(類似沙盒)而不是操作系統虛擬化,啟動速度快(秒級),存儲資源少(KB級或MB級),容器之間具有進程級隔離。壹臺電腦上可以運行上千個容器,這就是容器技術對虛擬機的滾動優勢。

1.2容器、鏡子和Docker

Docker是壹個開源的應用程序容器引擎,可以創建容器和基於容器運行的程序。Docker允許開發者將他們的應用程序和依賴項打包到壹個輕量級、可移植的容器中,然後發布到任何流行的Linux機器上,它也可以被虛擬化。

聽起來很簡單,但是Docker和container之間隱藏了壹個鏡像的概念,讓初學者相當困惑。Docker映像本質上是壹個特殊的文件系統,提供了容器運行時所需的程序、庫、資源、配置等文件。Docker鏡像類似於壹個py文件,需要Docker的運行時(類似於Python解釋器)才能運行。運行鏡像時,會創建鏡像的壹個實例,而實例是壹個容器。

1.3 Docker和k8s

作為壹個容器引擎,Docker為容器化的應用提供了壹個開放的標準,使開發者能夠以管理應用的方式管理基礎設施,實現代碼的快速交付、測試和部署。隨著集裝箱的廣泛使用,如何協調、調度和管理集裝箱的問題就產生了,Docker的集裝箱調度就應運而生。

K8s是Google的開源容器編排引擎,支持自動部署、大規模可擴展性和應用容器化管理。它是開源的,用於管理雲平臺中多臺主機上的容器化應用。k8s的目標是讓容器化應用的部署變得簡單高效,k8s提供了應用部署、規劃、更新和維護的機制。

Docker和k8sr都使用容器化(containerized standard)作為運行時,因此Docker創建的映像可以無障礙地在k8s中使用。

安裝在ubuntu中的2.1

在linux系統中安裝Docker非常簡單,官方為我們提供了壹鍵安裝腳本。這種方法也適用於Debian或CentOS等發行版。

如果安裝過程超時,不要灰心。多嘗試幾次,總會成功的。安裝後,Docker只能由root用戶使用。您可以使用以下命令取消權限限制:

然後,重新啟動docker服務:

最後,只需關閉當前命令行,然後重新打開新命令行。

順便說壹下,如果妳把它安裝在CentOS下,妳可能會得到壹堆類似下面的錯誤:

這是docker和Podman沖突造成的,所以需要先卸載Podman:

2.2 win 10中的安裝

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圖像查看命令。

目前,我只在本地安裝了兩個映像。

3.2從鏡像庫中找到鏡像。

執行命令docker search image name從docker圖像庫中查找圖像。

最好選擇官方形象,最穩定。

3.3下載新圖像

執行命令docker pull image name:version number下載新映像。

下載完映像後,您可以使用該映像來創建容器。

4.1啟動容器

執行命令docker run來啟動容器,也就是創建壹個鏡像實例。Docker運行命令非常復雜。您可以先執行docker運行幫助來查看幫助:

比如我們要執行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。

然後,使用-p參數。-p還需要三個參數,分別是主機的ip地址,主機的端口,容器的端口,在其中使用:分隔。壹般可以省略主機的ip地址,只寫主機的端口:容器的端口。

這樣,容器的5000端口映射到主機的5001端口,使用:

您可以連接到容器中的服務器。

4.4集裝箱管理

以上服務運行後,您可以使用docker ps命令來查看正在運行的容器:

顯示的內容包含以下各列:

要結束壹個容器,可以使用dockerkell容器ID命令。

壹般來說,我們的程序開發出來後,會和程序文件、運行環境壹起做成壹個新的鏡像。

要制作鏡像,需要編寫Dockerfile。DockeFile由多個命令組成,常用的命令有:

請註意,Docker圖像中有壹個層的概念。每次執行運行命令時,都會創建壹個層。過多的圖層會導致圖像文件的體積增加。盡量用&;& amp連接多個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命令中為我們的服務傳遞參數,而不是覆蓋execution命令,因此我們應該使用ENTRYPOINT而不是CMD:

上面的編寫方法不支持傳遞參數。ENTRYPOINT和CMD還支持另壹種書寫方法:

這樣,docker run命令中的參數可以傳遞給hello.py:

在這個命令中,- port=9000作為參數傳遞給hello.py,因此容器中的端口變為9000。

在生產環境中運行時,不使用-it選項,但使用-d選項使容器在後臺運行:

這樣,即使當前控制臺關閉,容器也不會停止。

5.3自制日程服務形象

接下來制作壹個apscheduler寫的服務鏡像,代碼如下:

Dockerfile也很方便:

生成鏡像:

它應該可以運行了。文件復制需要兩個目錄。在運行時,您可以使用-v兩次來掛載不同的目錄:

之前使用的官方python鏡像的大小是882MB。在此基礎上,通過安裝第三方庫,添加項目所需的資源,官方Python鏡像的大小可以輕松超過1 G。這麽大的圖像通過網絡傳輸給客戶非常不方便。因此,縮小圖像的尺寸是非常必要的。

docker hub上有壹個python:3.8-alpine鏡像,大小只有44.5MB,之所以小,是因為alpine是壹個busybox架構的操作系統,壹般用於嵌入式應用。我試著用了壹下這個鏡像,發現安裝通用庫還可以,但是安裝numpy之類的就很難了,甚至網上都找不到解決方案。

讓我們回到基本路線。主流的操作系統鏡像,ubuntu的大小是72.9MB,centos的大小是209 MB——這是我更喜歡用ubuntu的重要原因!以ubuntu為基礎鏡像,安裝python後的大小為139MB,安裝pip後的大小突然上升到407MB。如果再裝點別的,很容易趕上或者超過python官方鏡像的大小。

普通的途徑似乎很難壓縮圖像文件卷。好在還有曲線救國,就是多階段建造法。

多階段構建的思路其實很簡單。先構建壹個大而全的圖像,然後只把圖像中有用的部分拿出來放到新的圖像中。在我們的場景中,只有在構建圖像的過程中才需要pip,但是它對於運行我們的程序是沒有用的。我們只需要安裝pip,然後用pip安裝第三方庫,然後把第三方庫從這個鏡像復制到壹個沒有pip的python專用鏡像,這樣就可以節省pip占用的268MB空間。

1.基於ubuntu鏡像安裝python:

然後運行:

這樣就生成了壹個python:3.8-ubuntu鏡像。

2.安裝基於python的pip:3.8-Ubuntu:

然後運行:

這樣就生成了壹個python:3.8-ubuntu-pip鏡像。

3、多階段施工目標形象:

這個dockerfile需要解釋壹下,因為它有兩個FROM命令。

第壹個是安裝基於python的numpy:3.8-Ubuntu-pip鏡像。當然,在實際應用中,用到的第三方庫都寫在這裏。

第二個來自基於來自python:3.8-ubuntu的映像,它復制了所有第三方庫。COPY命令後的–from = 0表示從第0階段開始復制。在實際應用中,從上下文中復制程序代碼,添加需要的入口點。

最後,再次運行:

現在,我們項目的鏡像已經準備好了。它比用官方python映像構建的版本小了大約750MB。

至此,我們的映像已經制作完成,但是映像文件在哪裏,如何在生產環境中運行它呢?

當您剛剛使用docker images命令時,您已經看到了生成的圖像:

我們可以使用docker save命令將圖像保存到指定的文件中,並且保存的文件是壹個壓縮文件。tar格式:

將hello.tar復制到生產環境中的機器上,然後執行導入命令:

妳可以用它。

  • 上一篇:工業物聯網領域PLC廠家有哪些?
  • 下一篇:C++or c神秘國度的愛情故事 課題何解?
  • copyright 2024編程學習大全網