> For the complete documentation index, see [llms.txt](https://cutejaneii.gitbook.io/docker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cutejaneii.gitbook.io/docker/docker-image-1/zhuan-xie-dockerfile.md).

# 學習撰寫Dockerfile

## 當DockerHub無法滿足你的需求，就寫Dockerfile吧

Dockerfile是由一行一行的指令所構成，主要是利用這些指令來完成「映像檔的模樣」，可以參考別人寫好的Dockerfile，自己再稍微加工調整；也可以從無到有，撰寫自己的Dockerfile。

來看一個簡單的Dockerfile：

```
FROM python:3.6.8-alpine3.7                  # 基底映像檔是 python3.6.8 
MAINTAINER Jennifer <cutejaneii@hotmail.com> # 維護者資訊
COPY . /app                                  # 複製目前資料夾的檔案 至 映像檔內的/app資料夾
WORKDIR /app                                 # 切換工作目錄至 /app
RUN pip3 install -r requirements.txt         # pip3 install requirements.txt裡的套件
CMD ["python3", "main.py"]                   # 執行指令: python3 main.py
```

Dockerfile上常見的指令包括：

**`FROM`** 決定你的基底映像檔，例如 `FROM python:3.6.8-alpine3.7`、`FROM nginx:latest`

**`MAINTAINTER`** 定義維護者，例如 `MAINTERIN Jennifer <cutejaneii@hotmail.com>`

**`COPY`** 複製檔案至映像檔內，例如 `COPY . /app`

**`ADD`** 複製檔案至映像檔內，與`COPY`指令不同處有二個，一個是來源可以是URL（但不建議），第二個是若來源是TAR檔會自動解壓縮

**`RUN`** 用來執行你要在映像檔內的任何指令，例如 `RUN pip install h5py`、`RUN chmod +x entrypoint.sh`

**`ENV`** 設定環境變數，例如 `ENV HDF5_USE_FILE_LOCKING FALSE`、`ENV NGINX_MAX_UPLOAD 4m`，這個值也可於**docker run**時將參數值帶入，進行替換

**`ARG`** **docker build**時可將參數值帶入，進行替換

**`WORDDIR`** 切換目前的工作目錄，例如 `WORKDIR /app`

**`EXPOSE`** 設定要開放的PORT，但要docker run時也要下expose參數，例如 `EXPOSE 8080`

**`CMD`** 啟動Container時要執行的指令，例如 `CMD ["python3", "main.py"]`。CMD不一定會被執行，若docker run 有帶指令(docker run \[ContainerID] bash)，則會執行bash，而不執行CMD指令

**`ENTRYPOINT`** 啟動Container時要執行的指令，例如 `ENTRYPOINT ["docker-entrypoint.sh"]`，此指令一定會被執行。

**`ONBUILD`** 這個指令不會在建立時執行，而是別人將這一個Image設為基底Image時，才會執行的指令。執行的時機在FROM指令之後。指令例如 `ONBUILD RUN mkdir my_dir`

撰寫完畢後，使用`docker build`將目前的Dockerfile建立為Image

```
$ docker build -t jennifer/pythonapp .
```

{% hint style="info" %}
**`同場加映`**

`Dockerfile撰寫完畢後，可連同Image用到的檔案，一併上傳至Github，再透過Github與DockerHub的機制，讓DockerHub自動根據Github上的Dockerfile建立Image，可參考這篇：`[`連結Docker Hub/GitHub帳號，在Docker Hub自動建立Docker Image`](https://cutejaneii.wordpress.com/2017/05/03/docker-5-%e9%80%a3%e7%b5%90docker-hubgithub%e5%b8%b3%e8%99%9f%ef%bc%8c%e5%9c%a8docker-hub%e8%87%aa%e5%8b%95%e5%bb%ba%e7%ab%8bdocker-image/)
{% endhint %}
