docker-logo

Docker 承載你的所有心血,讓你的 App 可以在所有地方快速啟動

有了 Docker 之後,你的 App 就不需要煩惱開發環境跟真實部署的環境有相容性的問題,整包帶走!

可以看看 Docker 跟 Linux commands: https://www.youtube.com/watch?v=pTFZFxd4hOI&t=18s
同樣看看 Docker-compose: https://www.youtube.com/watch?v=HG6yIjZapSA

Docker 簡介

簡言之,有了 Docker 我們只需要寫好程式碼,使用 docker build 產生 Image,然後把 Image 帶到任何地方使用 docker run 開啟 Container 播種。

這個名字取得很棒!Docker(船塢)會根據 Image(build 出來的) 讓程式在 Container(貨櫃船)裡運作,我們只需要寫好 Dockerfile 或是 docker-compose.yml 定義 Image,然後使用 docker 命令產生 Image,另一部裝置就能直接使用你的 Image 建立 Container 執行。

概念其實有點像是 Python 的虛擬環境,也許你很熟悉 Anaconda,就是那個所謂的 Conda,只是 Python 虛擬環境是在隔離 Python 執行環境(僅針對 Python 語言),避免套件影響,而 Docker 則是把整個系統環境獨立(可以想像他在 MacOS 切了一角),可以在裡面執行你指定的套件、應用程式。

換句話說,你刪除了 Python,所有環境不論隔離與否都會沒了,而你刪除了 Docker,所有 Container 也都會沒了;Python 環境裡可以安裝套件,Docker Container 裡可以有 Python、Node.js、Java、ScyllaDB、MongoDB、Postgres。

稍微整理一下步驟

製作好你的 App 之後:

  1. 寫好 Dockerfile & (optional) docker-compose.yml
  2. docker build 產生 image
  3. docker run 使用 image

Using Docker

現在 Docker 有兩種使用方式:

  1. docker
  2. docker-compose

這兩個不同點是 docker 使用 Dockerfile,只會有一個 Container,而 docker-compose 使用 docker-compose.yml,會生出多個 Container,也可以直接在 docker-compose 裡定義使用其他的 Image。

例如你在開發 App 時執行了 ScyllaDB(一個好可愛的 Wide-Column NoSQL)做好的 Image,做為資料庫,使用 docker-compose 時就只需要在 .yml 裡面指定,就可以讓其他機器在執行時包含你的 App 和資料庫。

建立一個 my-remix-app

以下我會使用一個簡單的 Remix App 來示範。

// sh
# 安裝 remix
npx create-remix@latest

# 好了之後前往 app 的資料夾
cd my-remix-app

* Remix 是一個由 Shopify 維護的全端 React 框架,可以把前後端直接寫在同一個 JavaScript 中,直接幫你處理好前後端溝通的部分(不需要使用 fetch、ajax、axios) 。Reference: https://remix.run

Configure Dockerfile for “docker build”

在這裡面加上 Dockerfile,然後執行 build,完成後會產生一個 Image,然後 Tag(-t) 就是他的名字,所以你可以娶一個好分辨的名字,之後如果有要放上 Docker Hub 會比較好辨識。

然後如果有使用 npm install 的話,請記得在同個階層資料夾加上 .dockerignore 檔案,不然把整個 node_module 跟一堆 build 的東東複製過去製作成的 image 會很大包,我的程式碼大概 500MB,但產出的 image 大到 1.7GB 真的是下鼠我。

# ./Dockerfile
# :latest 會預設使用 Debian,這邊使用最小化的 alpine
FROM node:alpine
COPY package*.json ./
RUN npm install
# 複製其他資料到 build 的目的地
COPY . .
# 根據 README.md 的生產環境部署指示
RUN npm run build     # production 
CMD npm start         # production
EXPOSE 3000
# -t defining tag, . means the Dockerfile is right in the path
docker build -t tag-of-my-remix-app .

Running Docker Container

讓 Docker 使用剛剛建立的 “tag-of-my-remix-app”,然後把 port 設定為 3000,最後別忘了幫 Container 取的名字。

好了之後可以看看 localhost:3000 是不是有了!

# 記得加上 -d,不然你的終端機會直接顯示執行的內容
# 設定 localhost port 3000 : Docker port 3000
docker run --name container-mrp -p 3000:3000 -d tag-of-my-remix-app

Common docker Commands

# step 3
docker build -t name-of-image .
# step 4
docker run --name my-container -p 3000:3000 -d name-of-image
docker start my-container
docker stop my-container
# 強制停止
docker kill my-container
# 顯示所有 Container
docker ps -a
# 顯示運行中的 Container
docker ps
# 顯示所有 images
docker images
docker image ls
docker rm my-container
docker image rm name-of-image

Push Docker to Docker Hub

就像 GitHub 一樣,Docker 有一個 Docker Hub 可以儲存你 build 出來的 image,很簡單只要使用 docker push -t name-of-image 就可以直接把 image 提交上去 Docker Hub,不過現在他只限定可以使用一個免費 docker repository,另外在使用之前記得要先 docker login。

user@my-computer % docker login
Authenticating with existing credentials...
Login Succeeded

使用 Docker push。

user@my-computer % docker push -t tag-of-my-remix-app
Using default tag: latest
The push refers to repository [docker.io/username/tag-of-my-remix-app]
7343151d4d03: Pushed 
42d7ad2547df: Pushed 
427960a63f49: Mounted from library/node 
bcb4ca3fdb85: Mounted from library/node 
b3b6b803efc6: Mounted from library/node 
b09314aec293: Mounted from library/node 
latest: digest: sha256:e041234432112344321123443211234432112344321 size: 1579

這樣在你的 Docker Hub 就會看到一個跟 username/tag-of-my-remix-app 一樣的 repo 了!這樣之後如果要使用其他容器運行的雲端部署產品,就可以直接從雲端 pull 下來。