可以將應用程式、依賴打包成一個映像檔 (image) ,並在隔離環境內運行 (container)
sudo usermod -aG docker <user>
把使用者加進去 docker group
services:
nginx:
image: nginx
ports:
- 80:80docker compose up
放在 Docker Hub 上的 Image:
docker image ls
docker image inspect <image>
docker pull <image>
列出所有 host 上有的 image
查看某個 image 的 info
從 remote 拉取 image
隔離的執行環境
docker container ls
alias: docker ps
-a (也列出 stopped containers)
列出所有 host 上的 running containers
透過 YAML 設定檔,描述整個應用架構
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
backend:
build: ./backend
ports:
- "8080:8080"
environment:
DB_HOST: db
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: example
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:docker compose stop
docker compose down
docker compose up
-d (deattach console)
停止 container
停止 & 刪除 container
開啟 container
container 的 persistant 方式分成
server {
listen 80;
server_name localhost;
location / {
add_header Content-Type "text/plain";
return 200 "Hello!!!\n";
}
}
docker compose down
關 & 刪 container
mount 過去
services:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
docker compose up -d
開 container
services:
db:
image: postgres:16
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: password
POSTGRES_DB: testdb
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:跑起來 (寫進 docker-compose.yml)
再來,我們從 host 連去 pgSQL 看看
安裝 postgres client
連進去
CREATE TABLE test (content TEXT);
INSERT INTO test (content) VALUES ('a'), ('b');
SELECT * FROM test;
exit
建表
插資料
讀資料
離開 postgresql-client
docker compose down && docker compose up -d
psql -h 127.0.0.1 -U admin -d testdb
刪&關&開
連進去
\l
\c testdb
\dt
SELECT * FROM test;
list db
切到 testdb
list tables
讀資料
docker volume ls
docker volume inspect <vol>
docker volume rm <vol>
列出所有 host 上有的 volume
查看某個 volume 的 info
刪除 volume
包含一步驟的指令,用於建立 image
FROM <image>
RUN <command>
WORKDIR <dir>
COPY <src> <dest>
CMD <command>
你的 base image
建立新 layer,執行指令
設定 Dockerfile 的 working dir
把 host 上的檔案複製到 image
container 跑起來的時候,跑的指令
我們目前沒有東西可以打包成 image,我們先來寫東西吧
import express from "express";
import pg from "pg";
const app = express();
const client = new pg.Client({
host: "127.0.0.1",
user: "admin",
password: "password",
database: "testdb",
});
await client.connect();
app.get("/", async (req, res) => {
const result = await client.query("SELECT * FROM test");
res.json(result.rows);
});
app.listen(3328, '0.0.0.0', () => {
console.log("Server running on 3328");
});連接到 testdb
在 / 回傳 test 內的資料
{
"dependencies": {
"express": "^5.2.1",
"pg": "^8.20.0"
}
}幫你們跑過了,會長這樣
FROM node:20
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 3328
CMD ["node", "index.js"]docker build -t web .
-t 代表 tag (幫 image 命名)
docker image ls
把 web 加進去 compose
services:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
db:
image: postgres:16
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: password
POSTGRES_DB: testdb
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
web:
image: web
ports:
- "3328:3328"
volumes:
pgdata:
docker compose up -d
開 container
It's fucked up.
我們先不管這個問題,至少他跑起來了
build 區塊
services:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
db:
image: postgres:16
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: password
POSTGRES_DB: testdb
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
web:
image: web
build:
context: .
ports:
- "3328:3328"
volumes:
pgdata:在 up 的時候要求重新 build image
docker compose up --build
再來,看看我們的 image,看看有什麼問題
他超大的
FROM node:20
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 3328
CMD ["node", "index.js"]FROM node:20 AS builder
WORKDIR /app
COPY package.json .
RUN npm install
FROM node:20-slim
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3328
CMD ["node", "index.js"]也可以用 .dockerignore 避免打包不要的東西進去,像是 .git/
Bridge
container
Docker0
service name 會被解析成 container ip
所以,同個 network 內,可用 service name 作為 domain 跟其他 container 連線
address: 127.0.0.11
(127.0.0.0/8 是 loopback)
題外話 (nginx settings)
回到我們的 docker-compose.yml
services:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
db:
image: postgres:16
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: password
POSTGRES_DB: testdb
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
web:
image: web
ports:
- "3328:3328"
volumes:
pgdata:如果不寫 networks
會自動建立一個 (bridge)
自動包含所有 services
所以 web 連線到 postgres, 會用 "db" 這個 DN
services:
app:
networks:
- frontend
api:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:自己寫 networks 通常用於網路隔離
集中儲存、管理、分發 Image 的地方
像是 GitHub 儲存 git repo 一樣
註冊 docker.com
建立 PAT
docker login docker.io -u <username>
建立 Repository
重新 Build Dokcer Image
因為我們的 repo 名稱是 <username>/web
所以 image 也要同名
docker push <image>
services:
nginx:
image: nginx
ports:
- 80:80
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
db:
image: postgres:16
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: password
POSTGRES_DB: testdb
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
web:
image: speedcubing/web
ports:
- "3328:3328"
volumes:
pgdata:這時,我們的 image 如果改好
他就會去 Dockerhub pull
GitHub 用於存放 Docker Image 的服務
docker.io -> ghcr.io