# 學習撰寫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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cutejaneii.gitbook.io/docker/docker-image-1/zhuan-xie-dockerfile.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
