Dockerfile and docker-compose
9/12/2020 Taiwan Python 讀書會
10pm 開始
Ming-der Wang, 王銘德
(適合 Python/Docker 初學者)
用現成的 docker images
docker run -ti --rm -v ${HOME}:/root -v $(pwd):/git alpine/git
或自己做一個 docker image
vi Dockerfile
docker build -t mingder78/git .
docker run -ti --rm -v ${HOME}:/root -v $(pwd):/git mingder78/git
docker login
docker push mingder78/git
你只有兩個方法用 docker
Dockerfile
簡單講, 用它來 dockerize (docker 化) 你的 app,
(或別人的 app)
背景知識
* docker 底層是 Linux OS
* 所以需懂 Linux 指令
* 網路的基本概念
Linux 作業系統
每一行都是
指令 + 內容 (可以用 \ 跳行)
例如:
Dockerfile 的格式
FROM python:2.7
RUN mkdir /app
WORKDIR /app
COPY main.py /app/main.py
EXPOSE 5000 CMD ["python", "main.py"]
FROM
RUN
WORKDIR
ADD
EXPOSE CMD
VOLUME
ENV
COPY
LABEL
ENTRYPOINT
ONBUILD RUN
docker build
如何利用 Dockerfile 建立自己的 image (每次有改動, 就要重 build)
docker build -t mingder78/my_app:v1 .
在 Dockefile 的同一個目錄下, 執行以下 docker build 指令
當下目錄 (.)
tag 標註 (-t)
< docker id >/< app >:< tag >
(不能用大寫英文字母)
docker run
如何執行你剛出爐的 docker image
docker run -p 8080:5000 mingder78/my_app:v1
在 Dockefile 的同一個目錄下, 執行以下 docker build 指令
將 docker engine 的 8080 導到此 container 的 port 5000
用 docker images 指令可以找到你現在 docker engine 裡所有的 images
docker run -p ...
(容器可以轉 port 到不同之 docker engine 的 port)
docker engine
container (172.17.0.9)
container (172.17.0.8)
container (172.17.0.7)
container (172.17.0.6)
conatiner (172.17.0.5)
conatiner (172.17.0.4)
container (172.17.0.3)
同一台電腦裡可以裝多個 containers, 把 port 分開
IP: 192.168.1.100
6379
5000
9200
8080
8080
8081
5601
192.168.1.100:9200
192.168.1.100:5601
192.168.1.100:443
192.168.1.100:80
192.168.1.100:8080
192.168.1.100:5002
192.168.1.100:6379
docker run -p 443:8081 ...
web
瀏覽器
常用的 port numbers
知名Port即眾所周知的Port號,範圍從0到1023,這些Port號一般固定分配給一些服務。
比如:
21 Port分配給FTP服務,
25 Port分配給SMTP(簡單郵件傳輸協定)服務,
80 Port分配給HTTP服務,
443 Port分配給 HTTPS 服務等等。
其他 1024 ~ 65535 port 隨便你用, 但有些已經是知名 App 常用的 port了, 例如 Flask 用 5000
docker run -v ...
(容器可以掛載一堆本地端資料夾)
例如: docker run -it -v $PWD/rules:/usr/share/elastalert/rules ...
舉例ㄧ
用 docker 執行一個 nginx 網站, 但所有網頁資料, 並不是放在 docker images 裡, 而是要執行時, 才將網頁的內容目錄, 分享到 container 肚子裡.
好處是: 網頁內容可以修改, 而 docker images 不需重新 build.
舉例二
因為 docker container 刪除時, 所有 container 裡的目錄和所有檔案(資料) 全部消失.
所以, 如果我們開一個資料庫 container, 如何把資料庫的實體(目錄) 保持放在 container 外部目錄.
好處是: 資料不會消失
docker run -v 的目的
docker run 時
如何把外部資料放入 containers 裡
* 利用 volume 概念
可以是 docker engine 的某些目錄
或是用 docker volume 產生的共用 volumes
* 還可以設定 container 對該目錄或檔案的權限
docker engine (volume: xxx)
container (/data)
container (/app/data.csv)
container (/xxx/test.csv)
conatiner
conatiner
container
./data
/test/data.csv
docker-compose
docker-compose
簡單講, 幫你執行 docker 化的app
(兩支以上相關的 apps 需要同時執行, 利用
docker-compose.yml 檔案來描述其內容)
S
docker-compose 指令
用來執行 docker-compose.yml 的內容
如果 docker-compose.yml 有好幾個, 可以用 -f 指定, 例如
docker-compose -f chainlink-sgx.docker-compose.yml up
如何安裝 docker-compose
(如果無法執行 docker-compose, 再安裝)
也可以用 pip3 安裝
pip3 install docker-compose
docker-compose 常用指令
(一次全部 services 一起執行) docker-compose up docker-compose up -d (在背後執行) docker-compose up --build (Dockerfile 重新 build) docker-compose down
docker-compose down -v (連 volume 一起刪除)
docker-compose ps (看目前所有 services 狀態)
(僅用於單一 serivce)
docker-compose start docker-compose stop
docker-compose pause docker-compose unpause
docker-compose logs -f (看該 service 的 logs)
開始介紹
docker-compose.yml
它是 YAML 格式
YAML 格式簡介
YAML
是"YAML Ain't a Markup Language"
2001 年發明
強調這種語言以數據做為中心,而不是以標記語言為重點
幾乎所有語言都可以讀寫, 例如 Python 則透過 PyYAML 套件
pip install PyYAML
docker-compose.yml 會用到
kubernetes 也會用到
JSON
{ "hr": 65, "avg": 0.278, "rbi": 147 }
YAML
hr: 65 # Home runs
avg: 0.278 # Batting average
rbi: 147 # Runs Batted In
一筆 Python dict 資料
{'avg': 0.278, 'hr': 65, 'rbi': 147}
{ "hr": 65, "avg": 0.278, "rbi": 147 }
Python
Python
['Mark McGwire', 'Sammy Sosa', 'Ken Griffey']
YAML
- Mark McGwire
- Sammy Sosa
- Ken Griffey
一個字串的陣列
JSON
[ "Mark McGwire", "Sammy Sosa", "Ken Griffey" ]
Python
YAML
[{'avg': 0.278, 'hr': 65, 'name': 'Mark McGwire'}, {'avg': 0.288, 'hr': 63, 'name': 'Sammy Sosa'}]
-
name: Mark McGwire
hr: 65
avg: 0.278
-
name: Sammy Sosa
hr: 63
avg: 0.288
一個 dicts 的陣列
JSON
YAML
[ { "hr": 65, "avg": 0.278, "name": "Mark McGwire" }, { "hr": 63, "avg": 0.288, "name": "Sammy Sosa" } ]
-
name: Mark McGwire
hr: 65
avg: 0.278
-
name: Sammy Sosa
hr: 63
avg: 0.288
JSON 還是比較平易近人
YAML 獨有的
# Ranking of 1998 home runs
---
- Mark McGwire
- Sammy Sosa
- Ken Griffey
# Team ranking
---
- [name , hr, avg ]
- [Mark McGwire, 65, 0.278]
- [Sammy Sosa , 63, 0.288]
* 可以有註解 (#)
* 可以多檔, 寫在一檔裡 (---)
* 兩種 array 寫法都可以, [], -
(但 (-) 減號比較常用)
* 字串可無需用 (') 或 ('') 引號
---
id: 1
name: Ming-der Wang
scores: [99,100,36]
# Ranking of 1998 home runs
---
- Mark McGwire
- Sammy Sosa
- Ken Griffey
# Team ranking
---
- [name , hr, avg ]
- [Mark McGwire, 65, 0.278]
- [Sammy Sosa , 63, 0.288]
Dockerfile
FROM python:3.7-alpine WORKDIR /code ENV FLASK_APP app.py ENV FLASK_RUN_HOST 0.0.0.0 RUN apk add --no-cache gcc \ musl-dev linux-headers COPY requirements.txt \ requirements.txt RUN pip install -r \ requirements.txt EXPOSE 5000 COPY . . CMD ["flask", "run"]
docker-compose.yml
version: '3' services: web: build: . command: npm run serve ports: - "5000:5000" volumes: - .:/code environment: FLASK_ENV: development redis: image: "redis:alpine"
去 docker hub, 或 container registry 找 images
docker volume 說明
version: '3' services: web: build: . command: --config x ports: - "5000:5000" volumes: - dbdata:/db
volumes:
dbdata:
volumes 不一定是目錄
可以是 docker volume
depends_on 的說明
depends_on: 會等另一個 service 起來後才開始 run,
所以 redis: 會先起來, 後才開始執行 web:
version: '3' services: web: build: . command: --config x ports: - "5000:5000" volumes: - .:/code depends_on: - redis redis: image: "redis:alpine"
docker networks 的說明
web: service 在 frontend 網路“段" 執行
需定義 networks:
version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/code
networks: frontend:
networks: default: external: name: frontend
其他部分, 概念都跟 docker run 差不多
作業ㄧ
自己寫一個 Dockerfile 執行你自己的 Python 程式
(請用 git 把 Python 程式跟 Dockerfile 都放在同一目錄管理)
可 fork 參考 https://github.com/mingderwang/my-docker-for-python
作業二
利用 docker 開一個 jupyter 環境
(能把你的 jupyter 檔案一起放入更好)
提示: 利用 docker -v ...
Q&A
Ming-der Wang (王銘德)
Dockerfile and docker-compose
By Ming-der Wang
Dockerfile and docker-compose
- 958