網站首頁 編程語言 正文
前言
雖然Docker作為部署環境打包鏡像的工具,和我的科研并沒有直接的關系。但我覺得在項目中運用Docker來打包環境依賴也可以大大提高工作效率,于是準備專門學習一下Docker。
1. Docker基礎
1.1 Docker架構
Docker使用客戶端服務器架構。Docker客戶端與Docker守護進程會話,后者復雜構建、運行和分發Docker容器的繁重工作。Docker客戶端和守護程序可以在同一系統運行,也可以將Docker客戶端連接到遠程Docker守護進程。Docker客戶端和守護程序通過REST API(采用一種簡潔的URL風格規范)通信,其底層基于UNIX套接字或網絡接口。其架構示意圖如下:
其中,Docker 守護程序 (dockerd
) 監聽Docker API 請求并管理Docker對象,例如鏡像、容器、網絡和磁盤分卷。守護進程還可以與其他守護進程通信以管理Docker服務。而Docker 客戶端 (?docker
) 是用戶與 Docker 交互的主要方式。當我們使用諸如docker run
之類的命令時,客戶端會將這些命令發送到dockerd
執行它們。docker
命令使用 Docker API。Docker 客戶端可以與多個守護進程通信。
Docker注冊表存儲Docker鏡像(你可以類比為Maven的repo)。Docker Hub 是一個任何人都可以使用的公共注冊表,并且 Docker 默認配置為在Docker Hub上查找鏡像。我們也可以運行自己的私有注冊表。我們可以調用docker pull
從注冊表中拉取鏡像。當我們docker run
命令時,系統會從先從本地尋找鏡像,如果本地找不到,則會從Docker Hub拉取。當我們使用docker push
命令時,鏡像會被推送到我們配置的注冊表中。可以看出,Docker鏡像版本控制和Git類似。
1.2 Docker對象
當我們在使用Docker時,我們就正在創建和使用鏡像、容器、網絡、磁盤分卷、插件和其他對象了。下面簡要介紹一下其中的鏡像和容器對象。
鏡像?鏡像可視為一個只讀模板,其中包含創建 Docker 容器的指令。通常,一個鏡像基于另一個鏡像,并帶有一些額外的自定義。例如可以基于現有的ubuntu鏡像,來構建安裝有其它應用程序的鏡像。要構建我們自己的鏡像,需要使用簡單的語法創建一個Dockerfile ,用于定義創建和運行鏡像所需的步驟。
容器容器是鏡像的可運行實例(類似于進程和程序的關系)。我們可以使用 Docker API 或 CLI 創建、啟動、停止、移動或刪除容器。我們可以將容器連接到一個或多個網絡。
2. 啟動Docker進程并運行鏡像
2.1 啟動Docker守護進程
Linux
Linux上的docker同時包括客戶端和守護進程兩部分,故安裝好docker后,只需要用以下命令即可運行docker守護進程:
$ sudo service docker start # Ubuntu/Debian
如果您是RedHat/Centos,則需要運行:
$ sudo systemctl start docker
MacOS
然而,在Mac上docker二進制僅僅是client部分(因為docker守護進程使用了一些Linux內核的特點),我們不能使用它來運行docker守護進程。所以,我們還需要安裝docker-machine
來創建一個虛擬機并將守護進程運行在上面。如果你的Mac上已經有brew
,可以直接運行以下命令安裝:
brew install docker-machine
然后啟動docker-machine
:
(base) orion-orion@MacBook-Pro ~ % brew services start docker-machine ==> Successfully started `docker-machine` (label: homebrew.mxcl.docker-machine)
2.2 運行鏡像
之后我們就可以嘗試運行Docker鏡像了。比如我們下面用docker run
命令運行docker/getting-started
鏡像:
(base) orion-orion@MacBook-Pro ~ % docker run -d -p 80:80 docker/getting-started Unable to find image 'docker/getting-started:latest' locally latest: Pulling from docker/getting-started 9981e73032c8: Pull complete e5f90f35b4bc: Pull complete ab1af07f990a: Pull complete bd5777bb8f79: Pull complete a47abff02990: Pull complete d4b8ebd00804: Pull complete 6bec3724f233: Pull complete b95ca5a62dfb: Pull complete Digest: sha256:b558be874169471bd4e65bd6eac8c303b271a7ee8553ba47481b73b2bf597aae Status: Downloaded newer image for docker/getting-started:latest cc167092ff76941a25fe51da25fbbfe6a0a70cc07171fa5f56707f3bf7383e6a
可以看到由于沒有在本地找到docker/getting-started:latest
鏡像,Docker從遠處Docker Hub注冊表上pull下來。
我們用docker ps
查看目前在運行的鏡像實例(即容器):
(base) orion-orion@MacBook-Pro ~ % docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc167092ff76 docker/getting-started "/docker-entrypoint.…" 29 minutes ago Up 29 minutes 0.0.0.0:80->80/tcp epic_lehmann
可以用docker stop
終止鏡像運行:
(base) orion-orion@MacBook-Pro ~ % docker stop cc167092ff76 cc167092ff76 (base) orion-orion@MacBook-Pro ~ % docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
用docker images
查看有哪些本地鏡像:
(base) orion-orion@MacBook-Pro ~ % docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker/getting-started latest 157095baba98 4 weeks ago 27.4MB
3. 用Docker打包Python環境
接下來我們看如何用Docker打包一個Python環境。
首先,我們編寫一個Python小Demo:
import numpy as np import matplotlib.pyplot as plt x = np.arange(-10, 10, 0.01) y = x**2 plt.plot(x, y) plt.savefig("/out/quad.png") # 此處的/out為容器內的絕對路徑,無需手動創建, # 后面我們會設置掛載參數自動生成該目錄
然后我們編輯好requirements.txt
:
numpy==1.21.3 matplotlib==3.4.3
再編輯好Dockerfile
:
# syntax=docker/dockerfile:1 FROM python:3.9-slim-buster WORKDIR /draw_quad COPY requirements.txt requirements.txt RUN pip3 install -r requirements.txt COPY . . CMD [ "python3", "draw_quad.py"]
我們來細細看Dockerfile
每一部分。
首先,# syntax
是指解析器指令。這里使用docker/dockerfile:1
,即始終指向版本1語法的最新版本。
之后,我們需要告訴Docker我們在應用中使用什么基礎鏡像。由于Docker鏡像可以從其它鏡像繼承,因此我們并不構建自己的基礎鏡像,而是使用官方的Python鏡像,即FROM python:3.9-slim-buster
。
然后我們建立一個工作目錄/draw_quad
,即后續命令的默認執行路徑。這樣我們后面就不必輸入完整的文件路徑,而是可以使用基于工作目錄的相對路徑。如COPY requirements.txt requirements.txt
其實是將requirements
(第一個參數)復制到到工作目錄中(第二個參數)。
接著,我們將requirements.txt?
放入鏡像后,就可以使用RUN
命令來執行pip3 install
了,這和我們在本地安裝的經驗完全相同,不過這次是將模塊安裝到鏡像中。
此時,我們有了一個基于Python 3.9的鏡像,并且已經按照了我們的依賴項。下一步我們繼續用COPY
命令將源代碼添加到鏡像中,即DockerFile中的COPY . .
。
之后,我們還需要Docker當我們的鏡像在容器中運行時我們想要執行什么命令,即CMD [ "python3", "draw_quad.py"]
。
最終的項目目錄如下:
draw
|____ draw_quad.py
|____ requirements.txt
|____ Dockerfile
然后我們就可以構建docker鏡像了(用--tag
參數指定鏡像名稱):
(base) orion-orion@MacBook-Pro draw % docker build --tag draw . [+] Building 9.1s (14/14) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 37B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => resolve image config for docker.io/docker/dockerfile:1 4.9s => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:443aab4ca21183e069e7d8b2dc68006594f40bddf1b15bbd83f5137bd 0.0s => [internal] load build definition from Dockerfile 0.0s => [internal] load .dockerignore 0.0s => [internal] load metadata for docker.io/library/python:3.9-slim-buster 3.9s => [1/5] FROM docker.io/library/python:3.9-slim-buster@sha256:830e161433edfe047a23ebc99c12ee0eb1dc0a50e6b5f1c98e869ac27 0.0s => [internal] load build context 0.0s => => transferring context: 594B 0.0s => CACHED [2/5] WORKDIR /draw_quad 0.0s => CACHED [3/5] COPY requirements.txt requirements.txt 0.0s => CACHED [4/5] RUN pip3 install -r requirements.txt 0.0s => [5/5] COPY . . 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:18f3a254f4ce46faa17142ece6bfd442e9157e79510ca60a789ab4d4b1a12498 0.0s => => naming to docker.io/library/draw 0.0s
我們輸入docker images
命令可以看到名稱為draw
的鏡像已經構建成功。
(base) orion-orion@MacBook-Pro Draw % docker images REPOSITORY TAG IMAGE ID CREATED SIZE draw latest f1fc30becc34 46 seconds ago 251MB
然后就可以運行鏡像了(包含文件系統掛載操作):
(base) orion-orion@MacBook-Pro draw % docker run -d -v ${PWD}/out:/out draw 0e04d81d254fcd963924ee2492b82a6c895789525f09943b43ce0b46ac0d63a9
注意,${PWD}/out
為宿主機的目錄,意思為當前目錄下的out
文件夾,如果不存在則會自動為我們創建。/out
為該容器中的絕對路徑,在容器啟動會自動創建/out
目錄。
我們可以看到,quad.png
成功在宿主機當前目錄下的out
文件中生成:
(base) orion-orion@MacBook-Pro draw % ls out quad.png
參考
- [1]?https://docs.docker.com/get-started/overview/
- [2]?https://docs.docker.com/language/python/build-images/
- [3]?https://stackoverflow.com/questions/31448821/how-to-write-data-to-host-file-system-from-docker-container
- [4]?https://stackoverflow.com/questions/58205178/python-docker-filenotfounderror-errno-2-no-such-file-or-directory
- [5]?https://www.jb51.net/article/130032.htm
總結
原文鏈接:https://www.cnblogs.com/orion-orion/p/16268011.html
相關推薦
- 2022-05-23 iOS實現全局懸浮按鈕_IOS
- 2022-06-07 Python?urllib庫的使用指南詳解_python
- 2022-05-25 Flutter中抽屜組件Drawer使用詳解_Android
- 2023-05-20 Kotlin作用域函數使用示例詳細介紹_Android
- 2022-04-20 C語言特殊符號的補充理解_C 語言
- 2022-08-25 基于Python編寫一個點名器的示例代碼_python
- 2022-01-14 函數的防抖和節流&&深淺克隆
- 2022-09-19 Tomcat配置https?SSL證書的項目實踐_Tomcat
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支