---
title: Docker 學習 Dockerfile 製作
tags: Docker,CMD
---
Docker 學習 Dockerfile 製作
===
###### tags: `Docker` `CMD`
---
## :memo: Docker File 常用指令
<div class="dockerfile-description">
| 指令 | 描述 |
|:----------- |:---------------------------------------- |
| ADD | 添加本地或遠端的檔案和目錄。 |
| ARG | 於建置時所產生的變數。 |
| CMD | 指定預設命令。 |
| COPY | 複製檔案和目錄。 |
| ENTRYPOINT | 指定執行時預設指令檔。 |
| ENV | 設定環境變數。 |
| EXPOSE | 描述應用程式正在監聽的埠號。 |
| FROM | 從基礎映像檔創建新的建置階段。 |
| HEALTHCHECK | 在啟動時檢查容器的健康狀態。 |
| LABEL | 向映像檔添加元數據。 |
| MAINTAINER | 指定映像檔的作者。 |
| ONBUILD | 指定映像檔用於建置時的指令。 |
| RUN | 執行建置指令。 |
| SHELL | 設定映像檔的預設 Shell。 |
| STOPSIGNAL | 指定退出容器時的系統呼叫信號。 |
| USER | 設定使用者和群組 ID。 |
| VOLUME | 創建卷掛載。 |
| WORKDIR | 變更工作目錄,建立後都由該資料夾進行建置 |
</div>
---
## :pushpin: 什麼是Docker?
> Docker 是一塊開放式平台,目的是為了在**開發上可以達到快速部屬/測試/執行**
> 在Docker Hub上,由於 Docker 可拆分為前、中、後台程式專案及相關功能
> 可使用已存在的環境進行下載建置,已達到可重複且耦合性低的搭建手段
**Docker 其實也是 Virtual Machine 的一種,但不同於IIS伺服器架設**
:arrow_right: Docker 可以說是取代 VM 的功能,更為輕巧,簡便的使用架設服務
為什麼呢?
因為 VM 是可執行的Operation System,可創建虛擬平台**供使用者進行頁面操作**
但如果僅需要運行 IIS / HTTP 等架設網站需求服務,使用龐大的VM環境就顯得臃腫龐大
Docker 的好處就是<font color=red>**僅操作 Operation System 部份需求功能**</font>
針對所需使用的操作系統,無須浪費空間及大量的資源在用不到的功能上
---
## :rocket: 簡易DockerFile 撰寫
- DockerFile
```
ARG NODE_VERSION=20.11.1-alpine
FROM node:${NODE_VERSION}
LABEL description="A website about ANCO dessert" version="1.0.0" owner="MorgaYeh" email="a123a14795@gmail.com"
ENV PORT=3010
ENV WORK_PLACE=/ANCO
WORKDIR ${WORK_PLACE}
COPY public/ $WORK_PLACE/public
COPY src/ $WORK_PLACE/src
COPY package.json $WORK_PLACE/
COPY tailwind.config.js $WORK_PLACE/
RUN npm install
ENTRYPOINT ["npm", "run"]
CMD ["start"]
```
:pushpin: 根據以下步驟**可大略寫出所需的Dockerfile步驟**:
1. 確認專案程式環境,並使用FROM將其取得建置
2. 設定ENV變數,以利建置資料能統一參照使用
3. 選定WORKDIR位置,將環境建置起的需求文檔設定目錄於此
4. COPY環境建置須要的文件檔案至指定的WORKDIR位置
5. 執行/建立 RUN 指令(command),獲得須要的 package/jar... 等安裝包
6. 設定CMD執行指令,在docker build container時可預設建置,方便簡化建置流程
---
## :goal_net: 常用指令差別
### :dango: ADD v.s. COPY
<div class="docker-add-copy-compare">
| | COPY | ADD |
|:--------:|:----------------:|:----------------------:|
| **支援** | 複製建置平台資料 | HTTPS / Git URLS |
| **動作** | 僅複製至指定位置 | 可針對Wget/tar檔解壓縮 |
</div>
今天若有一檔案須<font color=red>**透過Http下載,且檔案為wget/tar副檔**</font>,則會建議使用ADD進行處理
若僅僅是在建置平台上,則會建議使用COPY方式操作
### :dango: ARG v.s. ENV
ARG 與 ENV 兩者皆為參數建置,**前者為runtime建置參數,後者為enviroment變數**
:arrow_down: **ENV的靈活度遠大於ARG的使用範圍**
<div class="docker-arg-env-compare">
| | ENV | ARG |
|:--------:|:-------------------------------------------------------------------------------:|:----:|
| 使用範圍 | ADD, COPY, ENV, EXPOSE, FROM, LABEL, STOPSIGNAL, USER, VOLUME, WORKDIR, ONBUILD | FROM |
</div>
若是想於 container建置時輸入指定參數,可使用 **ARG** 方式取得
```
ARG username
USER $username
...
------------------------------------------
$ docker build --build-arg username=MorgaYeh
```
另外,若想要建置時可輸入特定資料,或是不輸入資料以預設值方式帶出,可搭配 ARG/ENV 同時使用
```
#VERSION_1
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo %CONT_IMG_VER
#VERSION_2
ARG CONT_IMG_VER
ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}
RUN echo %CONT_IMG_VER
------------------------------------------
$ docker build --build-arg CONT_IMG_VER v2.0.8
```
:::info
**無輸入** ARG 參數,會以 **v1.0.0** 作為default參數使用
**有輸入** ARG 參數,會以輸入的值使用,如畫面上 **v2.0.8** 參數使用
:::
---
## :rocket: 進階練習:Docker Compose Build
### :clock1: 建置 SQL Server
```csharp
services:
db:
image: "mcr.microsoft.com/mssql/server"
ports:
- 8999:1433
volumes:
- sqlserverdata:/docker-entrypoint-initdb.d
environment:
SA_PASSWORD: "yarashi920!"
ACCEPT_EULA: "Y"
volumes:
sqlserverdata:
driver: local
```
- image : 基礎映像檔環境,可根據相對應版本,
- ports : <Outer Ports> : <Inner Ports>,用法同build container一樣
- environment : 環境變數設定
- volumes : 資料儲存放置位置,當Container重啟即將資料刷新,若含有volume可直接讀取使用
### :clock2: 建置 Front-End WebSite (待完成)
```csharp
services:
front-end:
volumes:
```
---
## :computer: 連結
<div class="link-Table">
| 參考網站 | 連結 |
|:-------------------- |:------------------------------:|
| Dockerfile reference | [:link:][Dockerfile reference] |
| Docker V.S. IIS | [:link:][Docker V.S. IIS]
[Dockerfile reference]: https://docs.docker.com/reference/dockerfile/
[Docker V.S. IIS]: https://stackoverflow.com/questions/30357679/difference-between-containers-docker-and-iis
</div>
<style>
div.link-Table > table th:nth-of-type(1) {
width: 90vw;
}
div.link-Table > table th:nth-of-type(2) {
width: 10vw;
}
div.dockerfile-description > table th:nth-of-type(1){
width: 30vw;
}
div.dockerfile-description > table th:nth-of-type(2){
width: 70vw
}
div.docker-arg-env-compare > table th:nth-of-type(1){
width: 10vw
}
div.docker-arg-env-compare > table th:nth-of-type(2){
width: 45vw
}
div.docker-arg-env-compare > table th:nth-of-type(3){
width: 45vw
}
div.docker-add-copy-compare > table th:nth-of-type(1){
width: 10vw
}
div.docker-add-copy-compare > table th:nth-of-type(2){
width: 45vw
}
div.docker-add-copy-compare > table th:nth-of-type(3){
width: 45vw
}
</style>