一、說明
????????在過去的 5 年里,我聽到了很多關于 docker 容器的嗡嗡聲。似乎我所有的軟件工程朋友都在使用它們來開發(fā)應用程序。我想弄清楚這項技術如何使我更有效率,但我發(fā)現(xiàn)網(wǎng)上的教程要么太詳細:闡明我作為數(shù)據(jù)科學家永遠不會使用的功能,要么太膚淺:沒有給我足夠的信息來幫助我了解如何快速有效地使用 Docker。
????????我寫了這個快速入門,所以你不必解析所有的信息,而是可以學習你需要知道的事情,以便快速入門。
二、什么是 Docker?
????????您可以將 Docker 視為輕量級虛擬機,其中包含運行應用程序所需的一切。docker 容器可以捕獲系統(tǒng)狀態(tài)的快照,以便其他人可以快速重新創(chuàng)建您的計算環(huán)境。這就是本教程需要了解的全部內(nèi)容,但有關更多詳細信息,您可以前往此處。
三、為什么要使用 docker?
- 可重復性:作為一名專業(yè)數(shù)據(jù)科學家,您的工作具有可重復性非常重要??芍貜托圆粌H有助于同行評審,而且確保您構建的模型、應用程序或分析可以毫無摩擦地運行,從而使您的可交付成果更加穩(wěn)健并經(jīng)得起時間的考驗。例如,如果你在python中構建了一個模型,僅僅運行pip-freeze并將結(jié)果的需求.txt文件發(fā)送給你的同事通常是不夠的,因為這只會封裝python特定的依賴項 - 而通常存在存在于python之外的依賴項,例如操作系統(tǒng),編譯器,驅(qū)動程序,配置文件或代碼成功運行所需的其他數(shù)據(jù)。即使你可以只共享 python 依賴項,將所有內(nèi)容包裝在 Docker 容器中也可以減輕其他人重新創(chuàng)建環(huán)境的負擔,并使你的工作更易于訪問。
- 計算環(huán)境的可移植性:作為數(shù)據(jù)科學家,尤其是在機器學習領域,能夠快速更改計算環(huán)境可以極大地影響您的工作效率。數(shù)據(jù)科學工作通常從原型設計、探索和研究開始——這些工作不一定需要專門的計算資源。這項工作通常發(fā)生在筆記本電腦或個人計算機上。但是,經(jīng)常會出現(xiàn)不同的計算資源會大大加快您的工作流程,例如具有更多 CPU 的機器或用于深度學習等功能的更強大的 GPU。我看到許多數(shù)據(jù)科學家將自己限制在本地計算環(huán)境中,因為在遠程計算機上重新創(chuàng)建本地環(huán)境存在摩擦。Docker 使移植環(huán)境(所有庫、文件等)的過程變得非常容易。在 Kaggle 競賽中,快速移植計算環(huán)境也是一個巨大的競爭優(yōu)勢,因為您可以以經(jīng)濟高效的方式利用 AWS 上寶貴的計算資源。最后,創(chuàng)建 docker 文件允許您移植許多您喜歡的本地環(huán)境,例如 bash 別名或 vim 插件。
-
增強您的工程能力:熟悉 Docker 可以讓您將模型或分析部署為應用程序(例如,作為可以提供預測服務的 REST API 端點),從而使其他人可以訪問您的工作。此外,作為數(shù)據(jù)科學工作流程的一部分,您可能需要與之交互的其他應用程序可能存在于 Docker 容器中,例如數(shù)據(jù)庫或其他應用程序。
四、Docker 術語
在我們深入之前,熟悉 Docker 術語很有幫助:
- 圖像:是您想要構建的藍圖。例如:帶有 Nvidia 驅(qū)動程序和正在運行的 Jupyter 服務器的 Ubuntu + TensorFlow。
- 容器:是您賦予生命的圖像的實例。您可以運行同一映像的多個副本。掌握鏡像和容器之間的區(qū)別非常重要,因為這是新手容易混淆的一個原因。如果圖像和容器之間的區(qū)別不清楚,請停止并再次閱讀。
- Dockerfile:創(chuàng)建映像的配方。Dockerfile 包含特殊的 Docker 語法。來自官方文檔:A 是一個文本文檔,其中包含用戶可以在命令行上調(diào)用以組裝圖像的所有命令。
Dockerfile
- 提交:與 git 一樣,Docker 容器提供版本控制。您可以通過提交更改隨時將 docker 容器的狀態(tài)另存為新映像。
- DockerHub/Image Registry:人們可以發(fā)布公共(或私有)docker 鏡像以促進協(xié)作和共享的地方。
- 層:對現(xiàn)有映像的修改,由 Dockerfile 中的指令表示。圖層按順序應用于基礎映像以創(chuàng)建最終映像。
????????我將在帖子的其余部分使用此術語,因此如果您迷路了,請參閱此列表!這些術語之間很容易混淆,尤其是在圖像和容器之間——所以在閱讀時要保持警惕!
五、創(chuàng)建您的第一個 Docker 鏡像
????????在創(chuàng)建 docker 容器之前,創(chuàng)建一個將定義映像的 Dockerfile 非常有用。讓我們慢慢地瀏覽下面的 Dockerfile??梢栽诒窘坛屉S附的 Github 存儲庫中找到此文件。
# reference: https://hub.docker.com/_/ubuntu/
FROM ubuntu:16.04
# Adds metadata to the image as a key value pair example LABEL version="1.0"
LABEL maintainer="Hamel Husain <youremail@gmail.com>"
##Set environment variables
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
RUN apt-get update --fix-missing && apt-get install -y wget bzip2 ca-certificates \
build-essential \
byobu \
curl \
git-core \
htop \
pkg-config \
python3-dev \
python-pip \
python-setuptools \
python-virtualenv \
unzip \
&& \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN echo 'export PATH=/opt/conda/bin:$PATH' > /etc/profile.d/conda.sh && \
wget --quiet https://repo.continuum.io/archive/Anaconda3-5.0.0.1-Linux-x86_64.sh -O ~/anaconda.sh && \
/bin/bash ~/anaconda.sh -b -p /opt/conda && \
rm ~/anaconda.sh
ENV PATH /opt/conda/bin:$PATH
RUN pip --no-cache-dir install --upgrade \
altair \
sklearn-pandas
# Open Ports for Jupyter
EXPOSE 7745
#Setup File System
RUN mkdir ds
ENV HOME=/ds
ENV SHELL=/bin/bash
VOLUME /ds
WORKDIR /ds
ADD run_jupyter.sh /ds/run_jupyter.sh
RUN chmod +x /ds/run_jupyter.sh
# Run a shell script
CMD ["./run_jupyter.sh"]
5.1 FROM?語句
FROM ubuntu:16.04
????????FROM?語句封裝了 Docker 最神奇的部分。此語句指定要在其上構建的基礎映像。使用 FROM 指定基本映像后,Docker 將在本地環(huán)境中查找名為?ubuntu:16.04?的映像 — 如果在本地找不到它,它將搜索您指定的 Docker 注冊表,默認情況下為?DockerHub。這種分層機制很方便,因為您經(jīng)常希望在 Ubuntu 等操作系統(tǒng)之上安裝程序。與其擔心如何從頭開始安裝 Ubuntu,不如簡單地在官方 Ubuntu 映像之上構建!Dockerhub上托管了各種各樣的Docker鏡像,包括那些提供的不僅僅是操作系統(tǒng)的鏡像,例如,如果你想要一個已經(jīng)安裝了Anaconda的容器,你可以在官方的anaconda docker鏡像之上構建一個容器。最重要的是,您還可以隨時發(fā)布您構建的映像,即使該映像是通過在另一個映像上分層創(chuàng)建的!可能性是無窮無盡的。
????????在這個例子中,我們指定我們的基礎映像是 ubuntu:16.04,它將查找一個名為 ubuntu 的?DockerHub 存儲庫。冒號 — 16.04 之后的映像名稱部分是允許您指定要安裝的基礎映像版本的標記。如果你導航到 Ubuntu?DockerHub 存儲庫,你會注意到不同版本的 Ubuntu 對應著不同的標簽:
????????例如,在撰寫本文時,ubuntu:16.04、ubuntu:xenial-20171201、ubuntu:xenial?和?ubuntu:latest?都引用了 Ubuntu 版本 16.04,并且都是同一映像的別名。此外,此存儲庫中提供的鏈接將您鏈接到用于為每個版本構建映像的相應 Dockerfile。您不會總是在 DockerHub 存儲庫中找到 Dockerfiles,因為維護者可以選擇包含他們?nèi)绾沃谱饔诚竦?Dockerfile。我個人發(fā)現(xiàn)查看其中幾個 Dockerfile 以更多地了解 Dockerfile 很有用(但請等到您完成本教程!
????????有一個標簽值得特別提及 —?:latest?標簽。此標記指定如果未在?FROM?語句中指定標記,則默認情況下將提取的內(nèi)容。例如,如果 FROM 語句如下所示:
FROM ubuntu
????????然后你最終會拉出 ubuntu:16.04 映像。為什么?— 如果你仔細看上面的截圖,你會看到 :latest 標簽與 16.04 相關聯(lián)
????????關于 Docker 鏡像的最后一點:從 DockerHub 隨機提取 Docker 鏡像時,要做出明智的判斷。由惡意行為者創(chuàng)建的 Docker 映像可能包含惡意軟件。
5.2 標簽聲明
????????此語句將元數(shù)據(jù)添加到映像中,并且是完全可選的。我添加它是為了讓其他人知道該聯(lián)系誰來了解該映像,也可以這樣我就可以搜索我的 docker 容器,尤其是當服務器上有許多容器同時運行時。
LABEL maintainer="Hamel Husain <youremail>"
5.3 環(huán)境聲明
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
????????這允許您更改環(huán)境變量,并且非常簡單。您可以在此處閱讀有關此內(nèi)容的更多信息。
5.4 運行語句
????????這通常是完成構建 Docker 映像所需的工作的主力。您可以運行任意 shell 命令(如?apt-get?和?pip install)來安裝所需的包和依賴項。
RUN apt-get update --fix-missing && apt-get install -y wget bzip2
build-essential \
ca-certificates \
git-core \
...
????????在這種情況下,我正在安裝一些我喜歡的實用程序,例如curl,htop,byobu,然后安裝anaconda,然后安裝基本anaconda安裝中沒有的其他庫(向上滾動到完整的Dockerfile以查看所有RUN語句)。
????????RUN?語句后面的命令與 Docker 無關,而是您自己安裝這些軟件包時會運行的普通 linux 命令,因此如果您不熟悉其中一些軟件包或 linux 命令,請不要擔心。另外,作為進一步的建議——當我第一次開始學習 docker 時,我查看了 Github 或 DockerHub 上的其他 Dockerfile,并將我想要的相關部分復制并粘貼到我的 Dockerfile 中。
????????關于 RUN 語句,您可能會注意到的一件事是格式設置。每個庫或包都整齊地縮進并按字母順序排列,以提高可讀性。這是 Dockerfiles 的普遍約定,所以我建議你采用它,因為它會簡化協(xié)作。
5.5 暴露語句
????????如果您嘗試公開端口,則此語句很有用 - 例如,如果您從容器或某種 Web 服務內(nèi)部提供 jupyter 筆記本。Docker的文檔在解釋EXPOSE?語句方面非常好:
該指令實際上并不發(fā)布端口。它充當構建映像的人和運行容器的人員之間的一種文檔類型,關于要發(fā)布的端口。若要在運行容器時實際發(fā)布端口,請使用標志 on 發(fā)布和映射一個或多個端口,或使用標志發(fā)布所有公開的端口并將其映射到高階端口。
EXPOSE
-p
docker run
-P
5.6 卷語句
VOLUME /ds
????????此語句允許您在 docker 容器和主機之間共享數(shù)據(jù)。VOLUME 語句允許您裝入外部裝入的卷。主機目錄僅在運行容器時聲明(因為您可能在不同的計算機上運行此容器),而不是在定義映像時聲明*。目前,您只需指定要與主機容器共享的 docker 容器中文件夾的名稱。
????????從 docker 用戶指南:
*主機目錄在容器運行時聲明:主機目錄(掛載點)本質(zhì)上依賴于主機。這是為了保持圖像的可移植性。因為無法保證給定的主機目錄在所有主機上都可用。因此,您無法從 Dockerfile 中掛載主機目錄。該指令不支持指定參數(shù)。創(chuàng)建或運行容器時必須指定裝入點。
VOLUME
host-dir
????????此外,這些卷旨在將數(shù)據(jù)保存在容器的文件系統(tǒng)之外,如果您正在處理不希望使 docker 映像膨脹的大量數(shù)據(jù),這通常很有用。保存 docker 映像時,此?VOLUME?目錄中的任何數(shù)據(jù)都不會保存為映像的一部分,但將保存容器中此目錄之外的數(shù)據(jù)。
5.7 工作路徑聲明
WORKDIR /ds
????????此語句設置工作目錄,以防要在另一個命令中引用沒有絕對路徑的特定文件。例如,Dockerfile 中的最后一條語句是
CMD [“./run_jupyter.sh”]
假設工作目錄為 /ds
5.8 ADD 語句
????????編輯 8/24/2020:您現(xiàn)在應該使用 COPY 語句而不是 ADD 語句。?
ADD run_jupyter.sh /ds/run_jupyter.sh
????????此命令允許您在運行 docker 容器時將文件從主機復制到 docker 容器中。我使用它來執(zhí)行 bash 腳本并將有用的東西導入容器中,例如 .bashrc 文件。
????????請注意,此處未完全指定主機容器的路徑,因為主機路徑相對于運行容器時指定的上下文目錄(稍后將討論)。
????????碰巧的是,當我運行這個容器時,我會將文件run_jupyter.sh在上下文目錄的根目錄中,所以這就是為什么源文件前面沒有路徑的原因。
????????從用戶指南:
ADD <src>... <dest>
該指令從中復制新文件、目錄或遠程文件 URL,并將它們添加到路徑 中的映像文件系統(tǒng)中。
ADD
<src>
<dest>
5.9 CMD聲明
????????Docker 容器的設計理念是它們是短暫的,只會保持足夠長的時間來完成要運行的應用程序。但是,對于數(shù)據(jù)科學,我們通常希望保持這些容器運行,即使其中沒有任何活動運行。許多人通過簡單地運行一個 bash shell(除非你殺死它,否則不會終止)來實現(xiàn)這一點的一種方式。
CMD [“./run_jupyter.sh”]
????????在上面的命令中,我正在運行一個實例化 Jupyter 筆記本服務器的 shell 腳本。但是,如果您沒有任何要運行的特定應用程序,但希望容器在不退出的情況下運行 — 則可以使用以下命令簡單地運行 bash shell:
CMD ["/bin/bash"]
????????這是有效的,因為 bash shell 在您退出之前不會終止,因此容器保持正常運行。
????????從用戶指南:
a 中只能有一個指令。如果您列出多個,則只有最后一個會生效。
CMD
Dockerfile
CMD
CMD
a 的主要目的是?為執(zhí)行容器提供默認值。這些默認值可以包含可執(zhí)行文件,也可以省略可執(zhí)行文件,在這種情況下,您還必須指定指令。
CMD
ENTRYPOINT
六、構建您的 Docker 鏡像
????????別擔心,從這里開始,其他一切都相當簡單?,F(xiàn)在我們已經(jīng)以 DockerFile 的形式創(chuàng)建了我們的配方,是時候構建映像了。您可以通過以下命令完成此操作:
也可在?Github?上使用
這將構建一個 docker 鏡像(不是容器,如果你不記得有什么區(qū)別,請閱讀本文開頭的術語?。?,然后你可以在以后運行它。
七、從 Docker 映像創(chuàng)建并運行容器
現(xiàn)在,您已準備好將所有這些魔力付諸實踐。我們可以通過執(zhí)行以下命令來啟動此環(huán)境:
????????也可在?Github?上使用
????????運行此命令后,您的容器將啟動并運行!Jupyter 服務器將運行,因為
CMD [“./run_jupyter.sh”]
????????命令在 Dockerfile 的末尾?,F(xiàn)在,您應該能夠在 jupyter 筆記本提供服務的端口上訪問它 — 在此示例中,它應該可以通過密碼教程從?http://localhost:7745/?訪問。?如果你遠程運行這個 docker 容器,你必須設置 local 端口轉(zhuǎn)發(fā),以便你可以從瀏覽器訪問 jupyter 服務器。
八、與容器交互
容器啟動并運行后,以下命令將派上用場:
- 將新的終端會話附加到容器。如果您需要安裝某些軟件或使用 shell,這將非常有用。
- 將容器的狀態(tài)另存為新映像。即使您一開始使用的是包含要安裝的所有庫的 Dockerfile,但隨著時間的推移,您可能會通過以交互方式添加更多庫和包來顯著更改容器的狀態(tài)。將容器的狀態(tài)另存為稍后可以共享或分層的圖像非常有用。您可以使用?docker commit?CLI 命令來完成此操作:
docker commit <container_name> new_image_name:tag_name(optional)
????????例如,如果我想將名為?container1?的容器的狀態(tài)保存為名為 hamelsmu/tutorial:v2 的圖像,我只需運行以下命令:
docker commit container_1 hamelsmu/tutorial:v2
????????你可能想知道為什么hamelsmu/在鏡像名稱的前面——這只是讓以后更容易地將這個容器推送到DockerHub,因為hamelsmu是我的DockerHub用戶名(稍后會詳細介紹)。如果您在工作中使用 Docker,則很可能有一個內(nèi)部私有 Docker 存儲庫,您可以將 Docker 映像推送到該存儲庫。
- 列出正在運行的容器。當我忘記當前正在運行的容器的名稱時,我經(jīng)常使用它。
docker ps -a -f status=running
如果您在沒有 status=running 標志的情況下運行上述命令,那么您將看到系統(tǒng)上所有容器的列表(即使它們不再運行)。這對于跟蹤舊容器很有用。
- 列出已保存在本地的所有圖像。
docker images
- 將您的映像推送到 DockerHub(或其他注冊表)。如果您想與他人共享您的工作,或方便地將圖像保存在云中,這將非常有用。請注意,在執(zhí)行此操作時不要共享任何私有信息(DockerHub上也有私有存儲庫)。
????????首先創(chuàng)建一個 DockerHub 存儲庫并適當?shù)孛挠诚瘢绱颂幩?。這將涉及運行命令docker login以首先連接到DockerHub或其他注冊表上的帳戶。例如,要將圖像推送到此容器,我首先必須將我的本地映像命名為 hamelsmu/tutorial(我可以選擇任何標簽名稱) 例如,CLI 命令:
docker push hamelsmu/tutorial:v2
????????將上述 docker 映像推送到帶有標記?v2?的此存儲庫。應該注意的是,如果你讓你的鏡像公開可用,其他人可以簡單地在你的鏡像上分層,就像我們在本教程中向?ubuntu?鏡像添加層一樣。這對于尋求復制或擴展您的研究的其他人非常有用。
九、現(xiàn)在你擁有超能力
現(xiàn)在您已經(jīng)知道如何操作 Docker,您可以執(zhí)行以下任務:文章來源:http://www.zghlxwxcb.cn/news/detail-614299.html
- 與同事和朋友分享可重復的研究。
- 通過根據(jù)需要將代碼臨時移動到更大的計算環(huán)境,在不破產(chǎn)的情況下贏得 Kaggle 比賽。
- 在筆記本電腦上的 docker 容器內(nèi)本地制作原型,然后將相同的計算無縫移動到服務器而不會出汗,同時隨身攜帶您喜歡的本地環(huán)境的許多東西(您的別名、vim 插件、bash 腳本、自定義提示等)。
- 使用?Nvidia-Docker?快速實例化在 GPU 計算機上運行 Tensorflow、Pytorch 或其他深度學習庫所需的所有依賴項(如果您從頭開始執(zhí)行此操作,這可能會很痛苦)。有關更多信息,請參閱下面的獎金部分。
- 將模型發(fā)布為應用程序,例如作為從 docker 容器提供預測的 rest api。當您的應用程序被 Docker 化時,可以根據(jù)需要多次復制它。
十、延伸閱讀
????????我們只是觸及了 Docker 的表面,您可以做的還有很多。我專注于Docker的領域,我認為作為數(shù)據(jù)科學家,你最常遇到的領域,并希望給你足夠的信心開始使用它。以下是一些在 Docker 之旅中幫助我的資源:文章來源地址http://www.zghlxwxcb.cn/news/detail-614299.html
- 編輯 8/24/2020:以下是我最近在 Docker 上所做的一些更詳細的筆記。
- 有用的 Docker 命令
- 更多有用的 Docker 命令
- Dockerfile 參考
- 如何在 DockerHub 上創(chuàng)建并推送到存儲庫
到了這里,關于Docker 如何助您成為數(shù)據(jù)科學家的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!