日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
如何將你的Python項目全面自動化?

 每個項目——無論你是在從事 Web 應用程序、數(shù)據(jù)科學還是 AI 開發(fā)——都可以從配置良好的 CI/CD、Docker 鏡像或一些額外的代碼質量工具(如 CodeClimate 或 SonarCloud)中獲益。所有這些都是本文要討論的內容,我們將看看如何將它們添加到 Python 項目中!

成都創(chuàng)新互聯(lián)是專業(yè)的金堂縣網(wǎng)站建設公司,金堂縣接單;提供成都做網(wǎng)站、成都網(wǎng)站制作,網(wǎng)頁設計,網(wǎng)站設計,建網(wǎng)站,PHP網(wǎng)站建設等專業(yè)做網(wǎng)站服務;采用PHP框架,可快速的進行金堂縣網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!

  •  在寫這篇文章之前,我還寫了一篇“Python 項目終極設置”,讀者感興趣的話,可以先讀下那一篇:https://martinheinz.dev/blog/14。
  •  GitHub 庫中提供了完整的源代碼和文檔:https://github.com/MartinHeinz/python-project-blueprint。

開發(fā)環(huán)境中可調試的 Docker 容器

有些人不喜歡 Docker,因為容器很難調試,或者構建鏡像需要花很長的時間。那么,就讓我們從這里開始,構建適合開發(fā)的鏡像——構建速度快且易于調試。

為了使鏡像易于調試,我們需要一個基礎鏡像,包括所有調試時可能用到的工具,像bash、vim、netcat、wget、cat、find、grep等。它默認包含很多工具,沒有的也很容易安裝。這個鏡像很笨重,但這不要緊,因為它只用于開發(fā)。你可能也注意到了,我選擇了非常具體的映像——鎖定了 Python 和 Debian 的版本——我是故意這么做的,因為我們希望最小化 Python 或 Debian 版本更新(可能不兼容)導致“破壞”的可能性。

作為替代方案,你也可以使用基于 Alpine 的鏡像。然而,這可能會導致一些問題,因為它使用musl libc而不是 Python 所依賴的glibc。所以,如果決定選擇這條路線,請記住這一點。至于構建速度,我們將利用多階段構建以便可以緩存盡可能多的層。通過這種方式,我們可以避免下載諸如gcc之類的依賴項和工具,以及應用程序所需的所有庫(來自requirements.txt)。

為了進一步提高速度,我們將從前面提到的python:3.8.1-buster創(chuàng)建自定義基礎鏡像,這將包括我們需要的所有工具,因為我們無法將下載和安裝這些工具所需的步驟緩存到最終的runner鏡像中。說的夠多了,讓我們看看Dockerfile:

 
 
 
  1. # dev.Dockerfile  
  2. FROM python:3.8.1-buster AS builder  
  3. RUN apt-get update && apt-get install -y --no-install-recommends --yes python3-venv gcc libpython3-dev && \  
  4.     python3 -m venv /venv && \  
  5.     /venv/bin/pip install --upgrade pip  
  6. FROM builder AS builder-venv  
  7. COPY requirements.txt /requirements.txt  
  8. RUN /venv/bin/pip install -r /requirements.txt  
  9. FROM builder-venv AS tester  
  10. COPY . /app  
  11. WORKDIR /app  
  12. RUN /venv/bin/pytest 
  13. FROM martinheinz/python-3.8.1-buster-tools:latest AS runner  
  14. COPY --from=tester /venv /venv  
  15. COPY --from=tester /app /app  
  16. WORKDIR /app  
  17. ENTRYPOINT ["/venv/bin/python3", "-m", "blueprint"]  
  18. USER 1001  
  19. LABEL name={NAME} 
  20.  LABEL version={VERSION} 

從上面可以看到,在創(chuàng)建最后的runner鏡像之前,我們要經(jīng)歷 3 個中間鏡像。首先是名為builder的鏡像,它下載構建最終應用所需的所有必要的庫,其中包括gcc和 Python 虛擬環(huán)境。安裝完成后,它還創(chuàng)建了實際的虛擬環(huán)境,供接下來的鏡像使用。接下來是build -venv鏡像,它將依賴項列表(requirements.txt)復制到鏡像中,然后安裝它。緩存會用到這個中間鏡像,因為我們只希望在requirement .txt更改時安裝庫,否則我們就使用緩存。

在創(chuàng)建最終鏡像之前,我們首先要針對應用程序運行測試。這發(fā)生在tester鏡像中。我們將源代碼復制到鏡像中并運行測試。如果測試通過,我們就繼續(xù)構建runner。

對于runner鏡像,我們使用自定義鏡像,其中包括一些額外的工具,如vim或netcat,這些功能在正常的 Debian 鏡像中是不存在的。

  •  你可以在 Docker Hub 中找到這個鏡像:https://hub.docker.com/repository/docker/martinheinz/python-3.8.1-buster-tools
  •  你也可以在base.Dockerfile 中查看其非常簡單的`Dockerfile`:https://github.com/MartinHeinz/python-project-blueprint/blob/master/base.Dockerfile

那么,我們在這個最終鏡像中要做的是——首先我們從tester鏡像中復制虛擬環(huán)境,其中包含所有已安裝的依賴項,接下來我們復制經(jīng)過測試的應用程序。現(xiàn)在,我們的鏡像中已經(jīng)有了所有的資源,我們進入應用程序所在的目錄,然后設置ENTRYPOINT,以便它在啟動鏡像時運行我們的應用程序。出于安全原因,我們還將USER設置為1001,因為最佳實踐告訴我們,永遠不要在root用戶下運行容器。最后兩行設置鏡像標簽。它們將在使用make目標運行構建時被替換 / 填充,稍后我們將看到。

針對生產環(huán)境優(yōu)化過的 Docker 容器

當涉及到生產級鏡像時,我們會希望確保它們小而安全且速度快。對于這個任務,我個人最喜歡的是來自 Distroless 項目的 Python 鏡像??墒?,Distroless 是什么呢?

這么說吧——在一個理想的世界里,每個人都可以使用FROM scratch構建他們的鏡像,然后作為基礎鏡像(也就是空鏡像)。然而,大多數(shù)人不愿意這樣做,因為那需要靜態(tài)鏈接二進制文件,等等。這就是 Distroless 的用途——它讓每個人都可以FROM scratch。

好了,現(xiàn)在讓我們具體描述一下 Distroless 是什么。它是由谷歌生成的一組鏡像,其中包含應用程序所需的最低條件,這意味著沒有 shell、包管理器或任何其他工具,這些工具會使鏡像膨脹,干擾安全掃描器(如 CVE),增加建立遵從性的難度。

現(xiàn)在,我們知道我們在干什么了,讓我們看看生產環(huán)境的Dockerfile……實際上,這里我們不會做太大改變,它只有兩行:

 
 
 
  1. # prod.Dockerfile  
  2. #  1. Line - Change builder image  
  3. FROM debian:buster-slim AS builder  
  4. #  ...  
  5. #  17. Line - Switch to Distroless image  
  6. FROM gcr.io/distroless/python3-debian10 AS runner  
  7. #  ... Rest of the Dockefile 

我們需要更改的只是用于構建和運行應用程序的基礎鏡像!但區(qū)別相當大——我們的開發(fā)鏡像是 1.03GB,而這個只有 103MB,這就是區(qū)別!我知道,我已經(jīng)能聽到你說:“但是 Alpine 可以更小!”是的,沒錯,但是大小沒那么重要。你只會在下載 / 上傳時注意到鏡像的大小,這并不經(jīng)常發(fā)生。當鏡像運行時,大小根本不重要。

比大小更重要的是安全性,從這個意義上說,Distroless 肯定更有優(yōu)勢,因為 Alpine(一個很好的替代選項)有很多額外的包,增加了攻擊面。關于 Distroless,最后值得一提的是鏡像調試??紤]到 Distroless 不包含任何 shell(甚至不包含sh),當你需要調試和查找時,就變得非常棘手。為此,所有 Distroless 鏡像都有調試版本。

因此,當遇到問題時,你可以使用debug標記構建生產鏡像,并將其與正常鏡像一起部署,通過 exec 命令進入鏡像并執(zhí)行(比如說)線程轉儲。你可以像下面這樣使用調試版本的python3鏡像:

 
 
 
  1. docker run --entrypoint=sh -ti gcr.io/distroless/python3-debian10:debug 

所有操作都只需一條命令

所有的Dockerfiles都準備好了,讓我們用Makefile實現(xiàn)自動化!我們首先要做的是用 Docker 構建應用程序。為了構建 dev 映像,我們可以執(zhí)行make build-dev,它運行以下目標:

 
 
 
  1. # The binary to build (just the basename).  
  2. MODULE := blueprint  
  3. # Where to push the docker image.  
  4. REGISTRY ?= docker.pkg.github.com/martinheinz/python-project-blueprint  
  5. IMAGE := $(REGISTRY)/$(MODULE)  
  6. # This version-strategy uses git tags to set the version string  
  7. TAG := $(shell git describe --tags --always --dirty)  
  8. build-dev:  
  9.  @echo "\n${BLUE}Building Development image with labels:\n"  
  10.  @echo "name: $(MODULE)"  
  11.  @echo "version: $(TAG)${NC}\n"  
  12.  @sed                                 \  
  13.      -e 's|{NAME}|$(MODULE)|g'        \  
  14.      -e 's|{VERSION}|$(TAG)|g'        \  
  15.      dev.Dockerfile | docker build -t $(IMAGE):$(TAG) -f- . 

這個目標會構建鏡像。它首先會用鏡像名和 Tag(運行git describe創(chuàng)建)替換dev.Dockerfile底部的標簽,然后運行docker build。

接下來,使用make build-prod VERSION=1.0.0構建生產鏡像:

 
 
 
  1. build-prod:  
  2.  @echo "\n${BLUE}Building Production image with labels:\n"  
  3.  @echo "name: $(MODULE)"  
  4.  @echo "version: $(VERSION)${NC}\n"  
  5.  @sed                                     \  
  6.      -e 's|{NAME}|$(MODULE)|g'            \  
  7.      -e 's|{VERSION}|$(VERSION)|g'        \  
  8.      prod.Dockerfile | docker build -t $(IMAGE):$(VERSION) -f- . 

這個目標與之前的目標非常相似,但是在上面的示例1.0.0中,我們使用作為參數(shù)傳遞的版本而不是git標簽作為版本 。當你運行 Docker 中的東西時,有時候你還需要在 Docker 中調試它,為此,有以下目標:

 
 
 
  1. # Example: make shell CMD="-c 'date > datefile'"  
  2. shell: build-dev  
  3.  @echo "\n${BLUE}Launching a shell in the containerized build environment...${NC}\n"  
  4.   @docker run                                                     \  
  5.    -ti                                                     \  
  6.    --rm                                                    \  
  7.    --entrypoint /bin/bash                                  \  
  8.    -u $$(id -u):$$(id -g)                                  \  
  9.    $(IMAGE):$(TAG)             \  
  10.    $(CMD) 

從上面我們可以看到,入口點被bash覆蓋,而容器命令被參數(shù)覆蓋。通過這種方式,我們可以直接進入容器瀏覽,或運行一次性命令,就像上面的例子一樣。

當我們完成了編碼并希望將鏡像推送到 Docker 注冊中心時,我們可以使用make push VERSION=0.0.2。讓我們看看目標做了什么:

 
 
 
  1. REGISTRY ?= docker.pkg.github.com/martinheinz/python-project-blueprint  
  2. push: build-prod  
  3.  @echo "\n${BLUE}Pushing image to GitHub Docker Registry...${NC}\n"  
  4.  @docker push $(IMAGE):$(VERSION) 

它首先運行我們前面看到的目標build-prod,然后運行docker push。這里假設你已經(jīng)登錄到 Docker 注冊中心,因此在運行這個命令之前,你需要先運行docker login。

最后一個目標是清理 Docker 工件。它使用被替換到Dockerfiles中的name標簽來過濾和查找需要刪除的工件:

 
 
 
  1. docker-clean:  
  2.  @docker system prune -f --filter "label=name=$(MODULE)" 

你可以在我的存儲庫中找到Makefile的完整代碼清單:https://github.com/MartinHeinz/python-project-blueprint/blob/master/Makefile

借助 GitHub Actions 實現(xiàn) CI/CD

現(xiàn)在,讓我們使用所有這些方便的make目標來設置 CI/CD。我們將使用 GitHub Actions 和 GitHubPackage Registry 來構建管道(作業(yè))及存儲鏡像。那么,它們又是什么呢?

  •  GitHub Actions 是幫助你自動化開發(fā)工作流的作業(yè) / 管道。你可以使用它們創(chuàng)建單個的任務,然后將它們合并到自定義工作流中,然后在每次推送到存儲庫或創(chuàng)建發(fā)布時執(zhí)行這些任務。
  •  GitHub Package Registry 是一個包托管服務,與 GitHub 完全集成。它允許你存儲各種類型的包,例如 Ruby gems 或 npm 包。我們將使用它來存儲 Docker 鏡像。如果你不熟悉 GitHub Package Registry,那么你可以查看我的博文,了解更多相關信息:https://martinheinz.dev/blog/6 。

現(xiàn)在,為了使用 GitHubActions,我們需要創(chuàng)建將基于我們選擇的觸發(fā)器(例如 push to repository)執(zhí)行的工作流。這些工作流是存儲庫中.github/workflows目錄下的 YAML 文件:

 
 
 
  1. .github  
  2. └── workflows  
  3.     ├── build-test.yml  
  4.     └── push.yml 

在那里,我們將創(chuàng)建兩個文件build-test.yml和push.yml。前者包含 2 個作業(yè),將在每次推送到存儲庫時被觸發(fā),讓我們看下這兩個作業(yè):

 
 
 
  1. jobs:  
  2.   build:  
  3.     runs-on: ubuntu-latest  
  4.     steps:  
  5.     - uses: actions/checkout@v1  
  6.     - name: Run Makefile build for Development  
  7.       run: make build-dev 

第一個作業(yè)名為build,它驗證我們的應用程序可以通過運行make build-dev目標來構建。

在運行之前,它首先通過執(zhí)行發(fā)布在 GitHub 上名為checkout的操作簽出我們的存儲庫。

 
 
 
  1. jobs:  
  2.   test:  
  3.     runs-on: ubuntu-latest  
  4.     steps:  
  5.     - uses: actions/checkout@v1  
  6.     - uses: actions/setup-python@v1  
  7.       with:  
  8.         python-version: '3.8'  
  9.     - name: Install Dependencies  
  10.       run: | 
  11.         python -m pip install --upgrade pip  
  12.         pip install -r requirements.txt  
  13.     - name: Run Makefile test  
  14.       run: make test  
  15.     - name: Install Linters  
  16.       run: |  
  17.         pip install pylint  
  18.         pip install flake8  
  19.         pip install bandit  
  20.     - name: Run Linters  
  21.       run: make lint 

第二個作業(yè)稍微復雜一點。它測試我們的應用程序并運行 3 個 linter(代碼質量檢查工具)。與上一個作業(yè)一樣,我們使用checkout@v1操作來獲取源代碼。在此之后,我們運行另一個已發(fā)布的操作setup-python@v1,設置 python 環(huán)境。要了解詳細信息,請查看這里:https://github.com/actions/setup-python 我們已經(jīng)有了 Python 環(huán)境,我們還需要requirements.txt中的應用程序依賴關系,這是我們用pip安裝的。

這時,我們可以著手運行make test目標,它將觸發(fā)我們的 Pytest 套件。如果我們的測試套件測試通過,我們繼續(xù)安裝前面提到的 linter——pylint、flake8 和 bandit。最后,我們運行make lint目標,它將觸發(fā)每一個 linter。關于構建 / 測試作業(yè)的內容就這些,但 push 作業(yè)呢?讓我們也一起看下:

 
 
 
  1. on:  
  2.   push:  
  3.     tags:  
  4.     - '*'  
  5. jobs:  
  6.   push:  
  7.     runs-on: ubuntu-latest  
  8.     steps:  
  9.     - uses: actions/checkout@v1  
  10.     - name: Set env  
  11.       run: echo ::set-env name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})  
  12.     - name: Log into Registry  
  13.       run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin  
  14.     - name: Push to GitHub Package Registry  
  15.       run: make push VERSION=${{ env.RELEASE_VERSION }} 

前四行定義了何時觸發(fā)該作業(yè)。我們指定,只有當標簽被推送到存儲庫時,該作業(yè)才啟動(*指定標簽名稱的模式——在本例中是任何名稱)。這樣,我們就不會在每次推送到存儲庫的時候都把我們的 Docker 鏡像推送到 GitHub Package Registry,而只是在我們推送指定應用程序新版本的標簽時才這樣做。

現(xiàn)在我們看下這個作業(yè)的主體——它首先簽出源代碼,并將環(huán)境變量RELEASE_VERSION設置為我們推送的git標簽。這是通過 GitHub Actions 內置的::setenv特性完成的(更多信息請查看這里:https://help.github.com/en/actions/automating-your-workflow-with-github-actions/development-tools-for-github-actions#set-an-environment-variable-set-env )。

接下來,它使用存儲在存儲庫中的 secretREGISTRY_TOKEN登錄到 Docker 注冊中心,并由發(fā)起工作流的用戶登錄(github.actor)。最后,在最后一行,它運行目標push,構建生產鏡像并將其推送到注冊中心,以之前推送的git標簽作為鏡像標簽。

感興趣的讀者可以從這里簽出完整的代碼清單:https://github.com/MartinHeinz/python-project-blueprint/tree/master/.github/workflows

使用 CodeClimate 進行代碼質量檢查

最后但同樣重要的是,我們還將使用 CodeClimate 和 SonarCloud 添加代碼質量檢查。它們將與上文的測試作業(yè)一起觸發(fā)。所以,讓我們添加以下幾行:

 
 
 
  1. # test, lint...  
  2. - name: Send report to CodeClimate  
  3.   run: |  
  4.     export GIT_BRANCH="${GITHUB_REF/refs\/heads\//}"  
  5.     curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter  
  6.     chmod +x ./cc-test-reporter  
  7.     ./cc-test-reporter format-coverage -t coverage.py coverage.xml  
  8.     ./cc-test-reporter upload-coverage -r "${{ secrets.CC_TEST_REPORTER_ID }}"  
  9. - name: SonarCloud scanner  
  10.   uses: sonarsource/sonarcloud-github-action@master  
  11.   env:  
  12.     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  
  13.     SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 

我們從 CodeClimate 開始,首先輸出變量GIT_BRANCH,我們會用環(huán)境變量GITHUB_REF來檢索這個變量。接下來,我們下載 CodeClimate test reporter 并使其可執(zhí)行。接下來,我們使用它來格式化由測試套件生成的覆蓋率報告,而且,在最后一行,我們將它與存儲在存儲庫秘密中的 test reporter ID 一起發(fā)送給 CodeClimate。至于 SonarCloud,我們需要在存儲庫中創(chuàng)建sonar-project.properties文件,類似下面這樣(這個文件的值可以在 SonarCloud 儀表板的右下角找到):

 
 
 
  1. sonar.organization=martinheinz-github  
  2. sonar.projectKey=MartinHeinz_python-project-blueprint  
  3. sonar.sources=blueprint 

除此之外,我們可以使用現(xiàn)有的sonarcloud-github-action,它會為我們做所有的工作。我們所要做的就是提供 2 個令牌——GitHub 令牌默認已在存儲庫中,SonarCloud 令牌可以從 SonarCloud 網(wǎng)站獲得。

注意:關于如何獲取和設置前面提到的所有令牌和秘密的步驟都在存儲庫的自述文件中:https://github.com/MartinHeinz/python-project-blueprint/blob/master/README.md

小  結

就是這樣!有了上面的工具、配置和代碼,你就可以構建和全方位自動化下一個 Python 項目了!如果關于本文討論的主題,你想了解更多信息,請查看存儲庫中的文檔和代碼:https://github.com/MartinHeinz/python-project-blueprint, 如果你有什么建議 / 問題,請在存儲庫中提交問題庫,或者如果你喜歡我的這個小項目,請為我點贊。


當前文章:如何將你的Python項目全面自動化?
文章URL:http://m.5511xx.com/article/codgeoj.html