Docker 學習
https://www.cnblogs.com/poloyy/p/15257059.html
專案結構
. ├── app │ ├── __init__.py │ └── main.py ├── Dockerfile └── requirements.txt
FastAPI 應用程式 main.py 程式碼
from typing import Optional from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"} @app.get("/items/{item_id}") def read_item(item_id: int, q: Optional[str] = None): return {"item_id": item_id, "q": q}
Dockerfile
# 1、從官方 Python 基礎映象開始 FROM python:3.9 # 2、將當前工作目錄設定為 /code # 這是放置 requirements.txt 檔案和應用程式目錄的地方 WORKDIR /code # 3、先複製 requirements.txt 檔案 # 由於這個檔案不經常更改,Docker 會檢測它並在這一步使用快取,也為下一步啟用快取 COPY ./requirements.txt /code/requirements.txt # 4、執行 pip 命令安裝依賴項 RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt # 5、複製 FastAPI 專案程式碼 COPY ./app /code/app # 6、執行服務 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
第四步:執行 pip 命令解析
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
- --no-cache-dir 選項告訴 pip 不要將下載的包儲存在本地,因為只有當 pip 將再次執行以安裝相同的包時才會這樣,但在使用容器時情況並非如此
- --no-cache-dir 只與pip有關,與 Docker 或容器無關
- --upgrade 選項告訴 pip 升級已經安裝的軟體包
- 因為上一步複製檔案可能會被 Docker 快取檢測到,所以這一步也會在 Docker 快取可用時使用
- 在這一步中使用快取會在開發過程中一次又一次地構建映象時節省大量時間,而不是每次都下載並安裝所有依賴項
Docker 快取
這裡有一個重要的技巧 Dockerfile,首先只複製依賴項的檔案,而不是 FastAPI 應用程式程式碼
COPY ./requirements.txt /code/requirements.txt
- Docker 和其他工具以增量方式構建這些容器映像,在另一層之上新增一層
- 從 Dockerfile 的頂部(首行)開始,由 Dockerfile 的每個指令來建立任何檔案
- Docker 和其他工具在構建映象時也是用內部快取
- 如果檔案自上次構建容器映象後沒有更改,則它將重用上次建立的同一層,而不是再次複製檔案並從頭開始建立一個新的層
- 僅僅避免檔案副本並不一定會改善太多,但是因為它在該步驟中使用了快取,所以它可以在下一步中使用快取
- 例如,它可以將快取用於安裝依賴項的指令
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
- requirements.txt 不會經常改變,所以通過複製該檔案,Docker 可以在該步驟中使用快取
- Docker 將能夠使用快取進行下一步下載和安裝這些依賴項,這就是節省大量時間的地方
- 下載並安裝該軟體包的依賴關係可能需要幾分鐘,但使用的快取將只需要幾秒
- 由於在開發過程中一次又一次地構建容器映象以檢查程式碼更改是否有效,因此可以節省大量累積時間
COPY ./app /code/app
- 在 Dockerfile 尾部,複製 FastAPI 應用程式程式碼
- 由於這是最常更改的內容,因此將其放在最後,在此步驟之後的任何內容都將無法使用快取
構建 Docker Image
在 Dockerfile 開啟命令列
docker build -t myimage .
檢視映象
docker images
啟動 docker 容器
docker run -d --name mycontainer -p 80:80 myimage
檢視容器
docker ps
訪問 127.0.0.1/
訪問 127.0.0.1/docs
帶有 Gunicorn 的官方 Docker 映象 - Uvicorn
- 此映象包含一個自動調整機制,可根據可用的 CPU 核心設定工作程式的數量
- 它具有合理的預設值,但仍然可以使用環境變數或配置檔案更新所有配置
- 此映象上的程式數是根據可用的 CPU 核心自動計算的,它將嘗試從 CPU 中榨取儘可能多的效能
- 但這也意味著,由於程式數取決於容器執行的 CPU,消耗的記憶體量也將取決於此
- 因此,如果應用程式消耗大量記憶體(例如使用機器學習模型),並且伺服器有很多 CPU 核心但記憶體很少,容器最終可能會使用比可用記憶體更多的記憶體,這會大大降低效能(甚至崩潰)
官方栗子
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 COPY ./requirements.txt /app/requirements.txt RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt COPY ./app /app
應用場景
- 如果正在使用 Kubernetes,並且已經設定了叢集級別的複製,就不應該使用此映象,最好從頭開始構建映象
- 如果應用程式足夠簡單,以至於根據 CPU 設定預設程式數效果很好,不想費心在叢集級別手動配置複製,並且執行的容器不會超過一個應用程式
- 或者如果使用 Docker Compose 進行部署,在單個伺服器上執行等
使用 poetry 的 docker image
# 第一階段:將僅用於安裝 Poetry 並從 Poetry 的 pyproject.toml 檔案生成帶有專案依賴項的 requirements.txt。 FROM tiangolo/uvicorn-gunicorn:python3.9 as requirements-stage # 將 /tmp 設定為當前工作目錄;這是我們將生成檔案requirements.txt的地方 WORKDIR /tmp # 安裝 poetry RUN pip install poetry # 複製 COPY ./pyproject.toml ./poetry.lock* /tmp/ # 生成 requirements.txt RUN poetry export -f requirements.txt --output requirements.txt --without-hashes # 這是最後階段,在這往後的任何內容都將保留在最終容器映像中 FROM python:3.9 # 將當前工作目錄設定為 /code WORKDIR /code # 複製 requirements.txt;這個檔案只存在於前一個 Docker 階段,這就是使用 --from-requirements-stage 複製它的原因 COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt # 執行命令 RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt # 複製 COPY ./app /code/app # 執行服務 CMD ["uvicorn", "app.1_快速入門:app", "--host", "0.0.0.0", "--port", "80"]
- 第一階段 Docker 是 Dockerfile 的一部分,它作為一個臨時容器的映象是僅用於生成一些檔案供後面階段使用
- 使用 Poetry 時,使用 Docker 多階段構建是有意義的
- 因為實際上並不需要在最終容器映象中安裝 Poetry 及其依賴項,只需要生成的 requirements.txt 檔案來安裝專案依賴項
poetry 詳細教程
https://www.cnblogs.com/poloyy/p/15267494.html