這裡使用pipreqs
進行依賴庫的識別。使用 pipreqs 可以自動檢索到當前項目下的所有組件及其版本,並生成 requirements.txt 文件。相比直接用pip freeze 命令,避免將整個python環境的依賴包寫入。
在項目的當前目錄中執行pipreqs ./ --encoding=utf8 --force
這裡使用的是一個基於flask項目,目錄結構如下
dockerfile定義python版本號,將本地項目進行拷貝,定義啟動命令。
這部分固定流程我們其實可以抽象出來通過自定義腳本去一鍵生成。這裡做一個簡單的示例。自動生成腳本見文末。
# 基於的基礎鏡像
FROM python:3.8.8
# 設置app文件夾是工作目錄
WORKDIR /usr/src/app
# 先將依賴文件拷貝到項目中
COPY requirements.txt /usr/src/app
# 執行指令,安裝依賴
RUN pip install -r requirements.txt
# 拷貝當前目錄的項目文件和代碼
COPY . /usr/src/app
# 執行命令
CMD [ "python", "/usr/src/app/app.py" ]
這裡以我自己寫的一個疫情可視化的flask項目為例,項目名稱為epidemic
docker build -f dockerfile -t epidemic .
這裡就是讀取項目目錄下的dockerfile進行構建-f
鏡像構建完成後使用docker run啟動容器,-p指定
docker run -it -p 5001:5000 --name epidemic_container epidemic
-p
指定端口映射,格式為:主機(宿主)端口:容器端口-i
: 以交互模式運行容器,通常與 -t 同時使用;-t
: 為容器重新分配一個偽輸入終端,通常與 -i 同時使用;
運行完成後我們就能看到如下界面,這裡的控制台輸出的就是此時容器中的flask運行控制台了。
我們本地訪問我們配置的映射端口即可,浏覽器輸入127.0.0.1:5001
即可
查看我們剛剛生成的容器。
通過腳本去將第二章中的dockerfile設置為模板,每次只需要自定義鏡像名稱即可,也可直接使用默認值。
腳本按如下邏輯依次執行
Created with Raphal 2.3.0 生成dockerfile 根據模板填充參數並生成dockerfile 檢查requirements.txt是否存在? 執行生成的dockerfile 根據鏡像配置參數啟動容器 結束 使用pipreqs生成requirements.txt yes no
完整代碼如下
import os
import sys
import time
def get_cmd(cmd):
res = os.popen(cmd)
return res.read()
class Generate:
def __init__(self, dockerfile_name="generate.dockerfile", image_name="docker_img"):
self.dockerfile_name = dockerfile_name
self.image_name = image_name
def generate_dockerfile(self, work_dir="/usr/src/app", main_file="app.py"):
# 首先生成dockerfile模板,python版本通過命令行獲取
python_version = sys.version.split(" ")[0]
template = f"""
FROM python:{python_version}
WORKDIR {work_dir}
COPY requirements.txt {work_dir}
RUN pip install -i https://pypi.doubanio.com/simple/ -r requirements.txt
COPY . {work_dir}
CMD [ "python", "{work_dir}/{main_file}" ]
"""
# 檢查requirements.txt文件是否存在,不存在則調用命令生成生成
if not os.path.exists("requirements.txt"):
print("正在等待requirements.txt文件生成,請稍候....")
os.system("pip install -i https://pypi.doubanio.com/simple/ pipreqs && pipreqs ./ --encoding=utf8 --force")
while not os.path.exists("requirements.txt"):
print("正在等待requirements.txt文件生成...")
time.sleep(2)
# 確定requirements文件生成後,將dockerfile寫入到本地
with open(self.dockerfile_name, "w") as f:
f.write(template)
print(f"dockerfile生成成功,文件名稱為{self.dockerfile_name}")
return True
def build_image(self):
images = get_cmd(f"docker images")
if self.image_name not in images:
cmd = f"docker build -f {self.dockerfile_name} -t {self.image_name} ."
print(cmd)
os.system(cmd)
return self.image_name in images
return False
def run_container(self, container_name, local_port=5001, container_port=5000):
cmd = f"docker run -p {local_port}:{container_port} --name {container_name} {self.image_name}"
#cmd = f"docker run {self.image_name}"
print(cmd)
os.system(cmd)
if __name__ == '__main__':
generate = Generate(dockerfile_name="generate_dockerfile.dockerfile", image_name="epidemic")
generate.generate_dockerfile()
generate.build_image()
generate.run_container(container_name="epidemic_container", local_port=5001, container_port=5000)
運行完成後的輸出如下
如果需要部署示例的這份源碼可以關注公眾號"一顆程序樹"在公眾號菜單進行獲取
先自我介紹一下,小編13年上師交大畢業,曾經在小公司待過,去過華為OPPO等大廠,18年進入阿裡,直到現在。深知大多數初中級java工程師,想要升技能,往往是需要自己摸索成長或是報班學習,但對於培訓機構動則近萬元的學費,著實壓力不小。自己不成體系的自學效率很低又漫長,而且容易碰到天花板技術停止不前。因此我收集了一份《java開發全套學習資料》送給大家,初衷也很簡單,就是希望幫助到想自學又不知道該從何學起的朋友,同時減輕大家的負擔。添加下方名片,即可獲取全套學習資料哦