1. 程式人生 > >Docker 使用雜記 - 最佳實踐嘗試 - 實戰

Docker 使用雜記 - 最佳實踐嘗試 - 實戰

[TOC] # Docker 使用雜記 - 最佳實踐嘗試 - 實戰 > 本文記錄了一個專案中使用docker構建環境的過程 ## Docker簡介 Docker NB!好了 其他簡介自己看網上吧 ![](https://img2020.cnblogs.com/blog/1007765/202003/1007765-20200315172148641-1708704336.png) ## 專案背景 ### 內在原因 這次的程式碼基於一個特定的tensorflow版本構建(才不是tf2跑不起來呢! ### 外在原因 與別人分享程式碼的時候就可以不用告訴他怎麼一步步配置環境了 並且基於GPU的Docker映象可以由nvidia-docker直接執行 ## 基礎映象 ### FROM ### 需求 #### Tensorflow==1.14 #### CUDA==10.0 #### cuDNN==7.4 #### openCV==3.4.2.16 俗話說好的開始是成功的一半 這次的基礎映象就由tensorflow官方搭的映象為基礎 看了一圈選擇了`tensorflow/tensorflow:1.14.0-gpu-py3` 地址在這[tensorflow:1.14.0-gpu-py3](https://hub.docker.com/layers/tensorflow/tensorflow/1.14.0-gpu-py3/images/sha256-e72e66b3dcb9c9e8f4e5703965ae1466b23fe8cad59e1c92c6e9fa58f8d81dc8?context=explore) 挺不錯 自帶GPU支援 要構建其他映象的同學也可以在`tags`裡面搜尋即可 全都有 ## 映象維護者 ### LABEL 這裡是說的`MAINTAINER`這個標籤 但是我剛敲出來 就發現 過期了(`deprecated` 上網一搜發現解決方案是用`LABEL` 最佳實踐: ``` LABEL maintainer="Licsber " ``` ## 工作資料夾 ### WORKDIR 顧名思義 制定容器內預設的資料夾 不指定的話預設就是`/`根目錄 ``` WORKDIR /home ``` ## 檔案 ### ADD `ADD`的好處是`tar.gz`檔案可以自動解壓 並且`ADD`可以從網路路徑拷貝檔案 任何情況下儘量不使用`ADD`(因為各種奇怪行為 ### COPY 顧名思義 `COPY`:拷貝檔案 語義明確 推薦使用 注意目標地址一定要是一個目錄(不然報錯 源地址拷貝會自動相當於有一個` /*`的拷貝 於是乎造成的特性就是隻拷貝資料夾內的內容 ``` COPY sources.list /etc/apt/ COPY model /home/model/ COPY *.py /home/ ``` 另外的特性就是可以使用萬用字元(符合Go語法即可(GoNB ## 宗卷 ### VOLUME 設定宗卷之後可以使用外接環境的內容了 ``` VOLUME /data ``` 掛載的方式:在`docker run`後面帶上引數 `-v $源路徑:$宗卷名稱`切記別反了(我第一次就反了 debug半天 例如: ``` sudo docker run -v /Users/licsber/Download:/data $專案名稱 ``` 這樣在映象內`/data`就能訪問到外接環境了 方便儲存結果 讀取檔案 ## 命令 ### RUN `RUN`用於執行命令 最佳實踐: ``` RUN apt update && apt install libsm6 libxrender1 libxext-dev ffmpeg -y && \ pip install -U -i https://pypi.tuna.tsinghua.edu.cn/simple pip && \ pip install matplotlib scipy ffmpy opencv-python==3.4.2.16 opencv-contrib-python==3.4.2.16 tqdm -i https://pypi.tuna.tsinghua.edu.cn/simple ``` 新手會把`RUN`命令寫多個 但是每一個Docker命令都會新建一層 這樣會讓層數特別多 於是 如果只是為了構建環境 一句話就夠 ## 入口點 ### ENTRYPORT 和`CMD`命令差不多 區別就是不會被預設替換 如果只定義`CMD` 空引數執行預設執行`CMD`裡的內容 如果只定義`CMD` 帶引數執行會覆蓋`CMD`定義的命令 ``` ENTRYPOINT ["python", "main.py"] ``` 這樣`映象名:tag`後面的引數就會預設追加到入口點了 ### CMD 另外需要注意的就是Docker沒有後臺的概念 如果在裡面寫這樣: ``` CMD service nginx start ``` 會發現容器秒退 因為Docker是容器 具體解釋參見[CMD容器啟動命令](https://yeasy.gitbooks.io/docker_practice/image/dockerfile/cmd.html) ## Dockerfile okk 看完了前面 終於到了重點 把這些命令一行行碼好 放到一個`Dockerfile`裡 就可以`build`了 `build`之後 `run` `push` 之類的操作豈不是順手拈來 另外可以看看阿里天池的Docker訓練 也能摸索`tag`的使用方法 還有關於tag的一個小坑 `latest` 這個自己谷歌吧 完整的Dockerfile貼在這: ``` FROM tensorflow/tensorflow:1.14.0-gpu-py3 LABEL maintainer="Licsber " WORKDIR /home VOLUME /data COPY sources.list /etc/apt/ RUN apt update && apt install libsm6 libxrender1 libxext-dev ffmpeg -y && \ pip install -U -i https://pypi.tuna.tsinghua.edu.cn/simple pip && \ pip install matplotlib scipy ffmpy opencv-python==3.4.2.16 opencv-contrib-python==3.4.2.16 tqdm -i https://pypi.tuna.tsinghua.edu.cn/simple COPY model /home/model/ COPY *.py /home/ ENTRYPOINT ["python", "Retargeting.py"] ``` ## 後記 話說`loop: 改程式碼 -> build同一個tag -> 執行`是不是最佳實踐呀? 實測產生大量\ 需要手動刪除 這裡貼出來一鍵程式碼:清理無用的docker映象 ``` alias dclean='sudo docker rmi $(docker images -f "dangling=true" -q)' ``` 沒錯 我就是電腦裡定義了`100+`alias的小天才(逃 ## 本文環境 Docker engine==19.03.5 ![](https://img2020.cnblogs.com/blog/1007765/202003/1007765-20200315172211152-1374916635.jpg) ## 參考 [Docker — 從入門到實踐](https://yeasy.gitbooks.io/docker_practice/) [Docker MAINTAINER Instruction](https://riptutorial.com/docker/example/11010/maintainer-instruction)