Docker 使用雜記 - 最佳實踐嘗試 - 實戰
阿新 • • 發佈:2020-03-15
[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)