為什麼人們在容器內開發?

為什麼人們在容器內開發?

九年前,也就是2013年3月,所羅門-海克斯和他的聯合創始人用一個名為Docker的開源平臺徹底改變了我們做軟體開發的方式。雖然Docker的創造者沒有發明容器,但他們普及了它們。多虧了Docker,工程師們可以建立工具,比如GitHub Codespaces,使我們能夠在雲端託管的開發容器中進行編碼。

我承認,當我第一次聽到開發容器的時候,我有兩個問題:

  • 為什麼人們要在容器內開發?
  • 容器是什麼?

如果你有類似的問題,這篇文章就是為你準備的。

在這篇博文中,我將解釋什麼是容器,它們如何使工程師受益,以及如何在GitHub程式碼空間中設定devcontainers。

在容器內開發是什麼意思?

如果你曾經說過 “它在我的機器上可以工作” 的話,請舉手。(別擔心,你不是一個人)!

在容器內開發是什麼意思?

如果你不熟悉這句話,它是一個備忘錄,但它也是一個真實的短語,如果開發人員發現他們在一個環境不同的程式碼庫中工作,他們會說這句話。雖然在不同的環境中工作並不理想,但它確實發生了。根據我的經驗,當我的本地環境、我同事的本地環境、暫存環境和生產環境都有輕微差異時,就會出現這樣的情況。因為環境的配置略有不同,所以錯誤在一個環境中存在,但在另一個環境中卻不存在。構建一個功能或修復一個bug,在本地可以使用,但在生產或暫存環境中卻不能使用,這可能會讓人感到非常尷尬和沮喪。

然而,容器解決了開發者環境不一致的問題。容器使軟體工程師能夠在一個一致的環境中程式設計。現在,你的編碼環境可以通過使用相同的作業系統、配置和依賴來反映生產。這確保了錯誤和功能在所有環境中的表現都是一樣的,從而使開發人員擺脫了說 “它在我的機器上能工作” 的尷尬局面。

現在我們瞭解了容器的目的,讓我們來探討一下Codespaces如何利用容器。

GitHub Codespaces將軟體和雲開發提升到新的水平

GitHub Codespaces允許你在託管在雲端的容器中進行編碼。在這種情況下,雲是一個不在你的電腦上而是在網際網路上的環境。

更快的入職培訓

通常情況下,軟體工程師在加入一個團隊時要負責設定他們的本地環境。本地環境的設定包括安裝所需的依賴項、林特、環境變數等。開發人員可能會花上一週的時間來配置他們的環境,這取決於文件的質量。當我還是純粹的軟體工程師時,我花了大約2天時間來設定我的環境,這個經歷是痛苦的,因為我想立即開始編碼。相反,我不得不為我的資料庫播種並編輯我的 .zshrc 檔案。

幸運的是,企業可以使用GitHub Codespaces配置自定義環境,使入職過程自動化。當一個新工程師加入團隊時,他們可以開啟一個程式碼空間,跳過本地環境設定,因為所需的擴充套件、依賴和環境變數都存在於codespace中。

從任何地方進行編碼

有了程式碼空間,我可以在任何可以上網的地方編碼。如果我換了裝置或把膝上型電腦忘在家裡,我可以在飛機上輕鬆地在iPad上繼續工作,而不需要克隆一個資源庫,下載我喜歡的IDE,並設定一個本地環境。這是可能的,因為Codespaces在瀏覽器內開啟一個類似Visual Studio程式碼的編輯器。最棒的是 Codespaces 可以自動儲存我的程式碼,即使我忘記把我的修改推送到我的倉庫。

一致的環境

正如上面幾段提到的,容器允許你在一個映象的生產環境中工作。因為GitHub Codespaces使用了容器,你可以在本地環境中獲得與生產環境相同的結果和開發者體驗。

此外,有時當程式碼庫發生變化時,例如基礎設施的增強,本地環境可能會中斷。當本地環境斷裂時,要由開發者來恢復他們的開發環境。然而,GitHub Codespaces對容器的使用給開發者環境帶來了統一性,減少了在破損環境中工作的機會。

你可能需要三個檔案來配置一個Codespace

你可以利用三個檔案來使Codespaces體驗對你和你的隊友有用: devcontainer.json 檔案、 Dockerfiledocker-compose.yml 檔案。這些檔案中的每一個都生活在你的倉庫根部的 .devcontainer 目錄下。

devcontainer.json檔案

devcontainer.json 檔案是一個配置檔案,它告訴 GitHub Codespaces 如何配置一個程式碼空間。在devcontainer檔案中,你可以配置以下內容:

  • 擴充套件程式
  • 環境變數
  • Dockerfile
  • 埠轉發
  • 建立後的命令
  • 還有更多

這意味著當你或別人開啟一個程式碼空間時,你在devcontainer.json檔案中指定的擴充套件、環境變數和其他配置將在他們開啟指定倉庫的程式碼空間時自動安裝。例如,如果我想讓人們擁有和我一樣的linter和擴充套件,我可以在我的devcontainer.json檔案中加入以下內容: devcontainer.json

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{
"name": "Node.js",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 18, 16, 14.
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local arm64/Apple Silicon.
"args": { "VARIANT": "16-bullseye" }
},
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"dbaeumer.vscode-eslint", // this is the exentension id for eslint
"esbenp.prettier-vscode", // this is the extension id for prettier
"ms-vsliveshare.vsliveshare", // this is the extension id for live share
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node"
}
{ "name": "Node.js", "build": { "dockerfile": "Dockerfile", // Update 'VARIANT' to pick a Node version: 18, 16, 14. // Append -bullseye or -buster to pin to an OS version. // Use -bullseye variants on local arm64/Apple Silicon. "args": { "VARIANT": "16-bullseye" } }, // Configure tool-specific properties. "customizations": { // Configure properties specific to VS Code. "vscode": { // Add the IDs of extensions you want installed when the container is created. "extensions": [ "dbaeumer.vscode-eslint", // this is the exentension id for eslint "esbenp.prettier-vscode", // this is the extension id for prettier "ms-vsliveshare.vsliveshare", // this is the extension id for live share ] } }, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. // "postCreateCommand": "yarn install", // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "node" }
 {
"name": "Node.js",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 18, 16, 14.
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local arm64/Apple Silicon.
"args": { "VARIANT": "16-bullseye" }
},
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"dbaeumer.vscode-eslint", // this is the exentension id for eslint
"esbenp.prettier-vscode", // this is the extension id for prettier
"ms-vsliveshare.vsliveshare", // this is the extension id for live share
]
}
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node"
}

你可以在這裡瞭解更多關於devcontainer.json檔案。

Dockerfile

Dockerfile是一個配置檔案,它告訴GitHub Codespaces如何構建一個容器。它包含一個Docker客戶端在建立映象時呼叫的命令列表。Dockerfile被用來自動安裝和配置一個容器。例如,如果我想在容器中安裝Node.js,我可以在我的Dockerfile中新增以下內容: Dockerfile

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
FROM node:16-bullseye
FROM node:16-bullseye
FROM node:16-bullseye

你可以在這裡瞭解更多關於Dockerfiles的資訊,你也可以在這裡瞭解更多關於在Codespaces中設定node.js的資訊。

docker-compose.yml檔案

在Codespace中你不需要docker-compose.yml檔案,但如果你想執行多個容器,它就很有用。例如,如果你想在一個Codespace中執行一個資料庫和一個Web伺服器,你可以使用docker-compose.yml檔案來執行這兩個容器。你可以在這裡瞭解更多關於docker-compose.yml檔案的資訊。下面是一個連線資料庫的docker-compose.yml檔案可能看起來像的例子: docker-compose.yml

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
version: '3.8'
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
args:
VARIANT: "3"
NODE_VERSION: "無"
volumes:
- ..:/workspace:cached
command: sleep infinity
network_mode: service:db
db:
image: postgres:latest
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
hostname: postgres
environment:
POSTGRES_DB: my_media
POSTGRES_USER: example
POSTGRES_PASSWORD: pass
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
volumes:
postgres-data: null
version: '3.8' services: app: build: context: .. dockerfile: .devcontainer/Dockerfile args: VARIANT: "3" NODE_VERSION: "無" volumes: - ..:/workspace:cached command: sleep infinity network_mode: service:db db: image: postgres:latest restart: unless-stopped volumes: - postgres-data:/var/lib/postgresql/data hostname: postgres environment: POSTGRES_DB: my_media POSTGRES_USER: example POSTGRES_PASSWORD: pass POSTGRES_HOST_AUTH_METHOD: trust ports: - 5432:5432 volumes: postgres-data: null
version: '3.8'
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
args:
VARIANT: "3"
NODE_VERSION: "無"
volumes:
- ..:/workspace:cached
command: sleep infinity
network_mode: service:db
db:
image: postgres:latest
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
hostname: postgres
environment:
POSTGRES_DB: my_media
POSTGRES_USER: example
POSTGRES_PASSWORD: pass
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
volumes:
postgres-data: null

Codespaces與GitHub的網路編輯器不一樣

GitHub Codespaces 與 GitHub 的網頁編輯器不同。網路編輯器是當你在倉庫中按下”. “時出現的編輯器。它是一個輕量級的編輯器,允許你編輯倉庫中的檔案。網頁編輯器很適合對檔案進行細微的修改,但對於編寫和執行全棧式網路應用程式來說,它並不理想。這是因為GitHub的網路編輯器沒有終端。然而,Codespaces允許你在瀏覽器中執行一個配備終端等功能的成熟的IDE。

請看下面的圖片,瞭解GitHub的網路編輯器和GitHub Codespaces的區別。這張圖片來自GitHub的官方文件。你可以在這裡閱讀更多細節。

GitHub的網路編輯器和GitHub Codespaces的區別

P.S. 我是用GitHub Copilot寫的這篇博文。 😉(這些都是我自己的文字、想法和挫折,但當我找不到合適的短語或動機時,Copilot幫助我解除了障礙。)via Rizèl Scarlett

評論留言