Pythonプロゞェクトでの䜜業の自動化



本日、Makefileを䜿甚しおPythonプロゞェクト甚にすばやくアセンブルされ簡単にデバッグできるDockerむメヌゞのビルドを自動化する、IBMDevOps゚ンゞニアによる蚘事の翻蚳を共有したす。このプロゞェクトは、Dockerでのデバッグを容易にするだけでなく、プロゞェクトコヌドの品質も管理したす。い぀ものように、詳现はカットの䞋にありたす。






デヌタサむ゚ンスたたはAIを䜿甚しおWebアプリケヌションで䜜業しおいる堎合でも、すべおのプロゞェクトは、適切に調敎されたCI / CD、開発䞭に同時にデバッグされ、実皌働環境甚に最適化されたDockerむメヌゞ、たたは品質保蚌ツヌルの恩恵を受けるこずができたす。CodeClimateやSonarCloudなどのコヌド。これらすべおがこの蚘事でカバヌされ、Pythonプロゞェクトにどのように远加されるかが瀺されおいたす。



開発甚のデバッグ可胜なコンテナ



コンテナのデバッグが難しい堎合や、むメヌゞの構築に時間がかかるため、Dockerを 嫌う人もいたす。それでは、開発に理想的なむメヌゞを構築するこずから始めたしょう-構築が速く、デバッグが簡単です。むメヌゞを簡単にデバッグするには、デバッグが必芁になる可胜性のあるすべおのツヌルを含むベヌスむメヌゞが必芁です。これらは、bash、vim、netcat、wget、cat、find、grepなどです。Python



むメヌゞ3.8.1-バスタヌこのタスクの完璧な候補のようです。箱から出しおすぐに䜿える倚くのツヌルが含たれおおり、䞍足しおいるツヌルを簡単にむンストヌルできたす。画像は倧きいですが、ここでは関係ありたせん。開発でのみ䜿甚されたす。お気づきかもしれたせんが、画像は非垞に具䜓的です。PythonずDebianのバヌゞョンをロックするこずは意図的なものです。぀たり、互換性のない可胜性のある新しいバヌゞョンのPythonたたはDebianによっお匕き起こされる砎損のリスクを最小限に抑える必芁がありたす。アンAlpine-ベヌスの画像は、代替ずしお可胜であるが、それはいく぀かの問題を匕き起こす可胜性がありたすそれは䜿甚しおいたす内偎MUSL libの代わりにはglibcをPythonが䟝存しおいる。アルパむンを遞択する堎合は、このこずに泚意しおください。速床に関しおは、マルチステヌゞビルドを䜿甚しお、できるだけ倚くのレむダヌをキャッシュしたす。そのため、gccなどの䟝存関係ずツヌル、およびアプリケヌションに必芁なすべおの䟝存関係が、requirements.txtから毎回ロヌドされるわけではありたせん。さらに高速化するために、前述のpython3.8.1-busterからカスタムベヌスむメヌゞが䜜成されたすrunner。これらのツヌルをダりンロヌドしお最終むメヌゞにむンストヌルするために必芁な手順をキャッシュできないため、必芁なものがすべお揃っおいたす。しかし、話をやめお、Dockerfileを芋おみたしょう。



# dev.Dockerfile
FROM python:3.8.1-buster AS builder
RUN apt-get update && apt-get install -y --no-install-recommends --yes python3-venv gcc libpython3-dev && \
    python3 -m venv /venv && \
    /venv/bin/pip install --upgrade pip

FROM builder AS builder-venv

COPY requirements.txt /requirements.txt
RUN /venv/bin/pip install -r /requirements.txt

FROM builder-venv AS tester

COPY . /app
WORKDIR /app
RUN /venv/bin/pytest

FROM martinheinz/python-3.8.1-buster-tools:latest AS runner
COPY --from=tester /venv /venv
COPY --from=tester /app /app

WORKDIR /app

ENTRYPOINT ["/venv/bin/python3", "-m", "blueprint"]
USER 1001

LABEL name={NAME}
LABEL version={VERSION}


䞊蚘では、最終的なrunner画像を䜜成する前に、コヌドが3぀の䞭間画像を通過するこずがわかりたす。 1぀目はビルダヌです。 gccやPython仮想環境など、アプリケヌションの構築に必芁なすべおのラむブラリをダりンロヌドしたす。むンストヌル埌、実際の仮想環境が䜜成され、次の画像で䜿甚されたす。次はbuilder-vvです。これは、䟝存関係のリストrequirements.txtをむメヌゞにコピヌしおから、それらをむンストヌルしたす。この䞭間むメヌゞはキャッシュに必芁です。requirements.txtが倉曎された堎合にのみラむブラリをむンストヌルしたす。それ以倖の堎合は、キャッシュを䜿甚したす。最終的な画像を䜜成する前に、アプリケヌションをテストしおみたしょう。



最終的なむメヌゞを䜜成する前に、たずアプリケヌションのテストを実行したしょう。゜ヌスコヌドをコピヌしお、テストを実行したす。テストに合栌したら、ランナヌ画像に移動したす。これは、通垞のDebianむメヌゞにはないいく぀かの远加ツヌルvimずnetcatを備えたカスタムむメヌゞを䜿甚したす。この画像は、䞊にあるドッカヌハブ、あなたはたた、非垞にシンプルなDockerfileで芋るこずができbase.Dockerfile。したがっお、この最終むメヌゞで行うこず最初に、テスタヌむメヌゞからむンストヌルしたすべおの䟝存関係が保存されおいる仮想環境をコピヌしたす。、次にテストしたアプリケヌションをコピヌしたす。すべおの゜ヌスがむメヌゞに含たれおいるので、アプリケヌションが配眮されおいるディレクトリに移動し、ENTRYPOINTをむンストヌルしお、むメヌゞの起動時にアプリケヌションが起動されるようにしたす。セキュリティ䞊の理由から、USERは1001に蚭定されおいたす。ベストプラクティスでは、コンテナをrootずしお実行しないこずをお勧めしたす。最埌の2行は、画像ラベルを蚭定したす。それらは、タヌゲットを介しお構築するずきに眮き換えられmakeたす。これに぀いおは、少し埌で説明したす。



実皌働環境向けに最適化されたコンテナ



プロダクショングレヌドの倖芳に関しおは、小さく、安党で、高速であるこずを確認する必芁がありたす。この意味での私の個人的なお気に入りは、DistrolessプロゞェクトのPythonむメヌゞです。しかし、「Distroless」ずは䜕ですかこのように蚀いたしょう。理想的な䞖界では、誰もがFROMスクラッチをベヌスずしお䜿甚しお独自の画像぀たり、空の画像を䜜成したす。しかし、バむナリなどを静的にリンクする必芁があるため、ほずんどの人が望んでいるこずではありたせん。そこでDistrolessが登堎したす。それは誰にずっおもFROMスクラッチです。そしお今、私は本圓に「Distroless」が䜕であるかをあなたに話したす。これはGoogleによっお䜜成されたセットですアプリケヌションに必芁な絶察最小倀を含む画像。これは、むメヌゞを膚らたせおセキュリティスキャナヌCVEなどの信号ノむズを生成するラッパヌ、パッケヌゞマネヌゞャヌ、たたはその他のツヌルがないこずを意味し、コンプラむアンスの確立を困難にしたす。䜕を扱っおいるかがわかったので、本番のDockerfileを芋おみたしょう。実際、コヌドをあたり倉曎する必芁はなく、2行だけ倉曎する必芁がありたす。




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


倉曎する必芁があるのは、アプリをビルドしお実行するためのベヌスむメヌゞだけでした。しかし、その違いはかなり倧きいです。開発むメヌゞの重量は1.03 GBで、これはわずか103 MBでした。これは、倧きな違いです。そしお、私はすでにあなたの蚀うこずを聞くこずができたす「アルピナはさらに軜くするこずができたす」 ..。はい、そうですが、サむズはそれほど重芁ではありたせん。ロヌド/アンロヌド時に画像のサむズに気付くだけで、それほど頻繁には発生したせん。画像が機胜する堎合、サむズは関係ありたせん。どのような倧きさよりも重芁なのはセキュリティであり、この点でDistrolessは間違いなくアルパむンに優れおいるアルパむンは攻撃面を高めるために倚くの远加のパッケヌゞを持っおいたす。Distrolessに぀いお話すずきに蚀及する䟡倀のある最埌のこずは、画像のデバッグです。それを考慮しおDistrolessにはシェルが含たれおおらず「sh」も含たれおいたせん、デバッグず調査は非垞に困難になりたす。このために、すべおのDistrolessむメヌゞの「デバッグ」バヌゞョンがありたす。そうすれば、問題が発生したずきに、タグdebugを䜿甚しお䜜業むメヌゞを䜜成し、通垞のむメヌゞず䞀緒にデプロむし、デバッグむメヌゞで必芁な凊理を実行しお、たずえばストリヌムダンプを実行できたす。次のように、python3むメヌゞのデバッグバヌゞョンを䜿甚するこずができたす。



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


すべおのための1぀のチヌム



すべおのDockerfileの準備ができたら、Makefileを䜿甚しおこの悪倢党䜓を自動化できたす。最初に実行したいのは、Dockerを䜿甚しおアプリケヌションをビルドするこずです。したがっお、開発むメヌゞを構築するために、make build-dev次のコヌドを実行するものを蚘述したす。




# The binary to build (just the basename).
MODULE := blueprint

# Where to push the docker image.
REGISTRY ?= docker.pkg.github.com/martinheinz/python-project-blueprint

IMAGE := $(REGISTRY)/$(MODULE)

# This version-strategy uses git tags to set the version string
TAG := $(shell git describe --tags --always --dirty)

build-dev:
 @echo "\n${BLUE}Building Development image with labels:\n"
 @echo "name: $(MODULE)"
 @echo "version: $(TAG)${NC}\n"
 @sed                                 \
     -e 's|{NAME}|$(MODULE)|g'        \
     -e 's|{VERSION}|$(TAG)|g'        \
     dev.Dockerfile | docker build -t $(IMAGE):$(TAG) -f- .




このタヌゲットは、最初に䞋郚のラベルをdev.Dockerfile画像の名前ず起動によっお䜜成されたタグに眮き換えるこずによっお画像を䜜成しgit describe、次に起動しdocker buildたす。次に、以䞋を䜿甚しお実皌働環境甚にビルドしたすmake build-prod VERSION=1.0.0。




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


このタヌゲットは前のタヌゲットず非垞に䌌おいたすが、バヌゞョンずしおgitタグを䜿甚する代わりに、匕数ずしお枡されたバヌゞョンが䜿甚されたす。䞊蚘の䟋では、1.0.0です。すべおがで実行されおいる堎合ドッカヌ、いく぀かの時点で、あなたはたた、デバッグすべおに必芁ドッカヌ。これには目暙がありたす。




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


䞊蚘のコヌドでは、゚ントリポむントがbashによっおオヌバヌラむドされ、containerコマンドがCMDの匕数によっおオヌバヌラむドされおいるこずがわかりたす。したがっお、コンテナに移動しお移動するか、䞊蚘の䟋のように䜕らかのコマンドを実行するこずができたす。プログラミングずDockerレゞストリぞのむメヌゞのプッシュが完了したら、を䜿甚できたすmake push VERSION=0.0.2。この目暙が䜕をするか芋おみたしょう




REGISTRY ?= docker.pkg.github.com/martinheinz/python-project-blueprint

push: build-prod
 @echo "\n${BLUE}Pushing image to GitHub Docker Registry...${NC}\n"
 @docker push $(IMAGE):$(VERSION)


最初に前述のタヌゲットを起動し、build-prod次に単玔に起動しdocker pushたす。これは、Dockerレゞストリにログむンしおいるこずを前提ずしおいるため、を実行する前にこのタヌゲットを実行する必芁がありたすdocker login。最終的な目暙は、Dockerアヌティファクトをクリヌンアップするこずです。これは、Dockerむメヌゞビルドファむル内で眮き換えられたnameタグを䜿甚しお、削陀する必芁のあるアヌティファクトをフィルタリングおよび怜玢したす。




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


すべおのMakefileコヌドはリポゞトリにありたす。



GitHubアクションを含むCI / CD



このプロゞェクトでは、make、Github Actions、およびGithubパッケヌゞレゞストリを䜿甚しおパむプラむンタスクを構築し、むメヌゞを保存しおCI / CDを構成したす。しかし、それは䜕ですか



  • GitHubアクションは、開発ワヌクフロヌの自動化に圹立぀タスク/パむプラむンです。それらを䜿甚しお個別のタスクを䜜成し、それらを組み合わせおカスタムワヌクフロヌにするこずができたす。カスタムワヌクフロヌは、たずえば、リポゞトリにデヌタを送信するたびに、たたはリリヌスを䜜成するずきに実行されたす。
  • Github Package Registryは、 GitHubず完党に統合されたパッケヌゞホスティングサヌビスです。Ruby gemやnpmパッケヌゞなど、さたざたなタむプのパッケヌゞを保存できたす。プロゞェクトはこれを䜿甚しおDockerむメヌゞを保存したす。Githubパッケヌゞレゞストリの詳现に぀いおは、こちらをご芧ください。


GitHubアクション を䜿甚するには、遞択したトリガヌに基づいおプロゞェクトにワヌクフロヌを䜜成したすトリガヌの䟋はリポゞトリぞの送信です。これらのワヌクフロヌは、ディレクトリ内のYAMLファむルです.github/workflows。




.github
└── workflows
    ├── build-test.yml
    └── push.yml


build-test.ymlファむルには、コヌドがリポゞトリに送信されるたびに実行される2぀のゞョブが含たれおいたす。これらのゞョブを以䞋に瀺したす。




jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Run Makefile build for Development
      run: make build-dev


ビルドず呌ばれる最初のタスクは、タヌゲットを実行しおアプリケヌションをビルドできるこずを確認したすmake build-dev。ただし、開始する前に、checkoutGitHubに公開されたリポゞトリを実行しおリポゞトリをチェックしたす。






jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - uses: actions/setup-python@v1
      with:
        python-version: '3.8'
    - name: Install Dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run Makefile test
      run: make test
    - name: Install Linters
      run: |
        pip install pylint
        pip install flake8
        pip install bandit
    - name: Run Linters
      run: make lint


2番目のタスクはもう少し難しいです。アプリケヌションの隣でテストを実行し、3぀のコヌド品質管理リンタヌコヌド品質コントロヌラヌを実行したす。前のタスクず同様に、アクションを䜿甚しお゜ヌスコヌドを取埗したすcheckout@v1。その埌setup-python@v1、python環境をセットアップする、ず呌ばれる別の公開されたアクションが起動されたす詳现はこちら。 Python環境ができたので、requirements.txtpipを䜿甚しおむンストヌルするアプリケヌションの䟝存関係が必芁です。この時点make testで、タヌゲットの実行を開始したしょう。タヌゲットはPytestテストスむヌトを実行したす。キットのテストに合栌した堎合は、前述のリンタヌpylint、flake8、banditのむンストヌルに進みたす。最埌に、タヌゲットを起動したすmake lint次に、これらの各リンタヌを起動したす。ビルド/テストゞョブがすべおですが、コヌドを送信するのはどうですか圌女に぀いお話したしょう




on:
  push:
    tags:
    - '*'

jobs:
  push:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Set env
      run: echo ::set-env name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})
    - name: Log into Registry
      run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login docker.pkg.github.com -u ${{ github.actor }} --password-stdin
    - name: Push to GitHub Package Registry
      run: make push VERSION=${{ env.RELEASE_VERSION }}


最初の4行は、ゞョブの開始時間を定矩したす。このタスクは、タグがリポゞトリに移動されたずきにのみトリガヌされる必芁があるこずを瀺したす*は名前のパタヌンを瀺し、ここではすべおタグです。これは、デヌタをリポゞトリにプッシュするたびにDockerむメヌゞをGitHubパッケヌゞレゞストリにプッシュしないようにするためですが、アプリケヌションの新しいバヌゞョンを瀺すタグがアップロヌドされた堎合にのみ行われたす。ここで、このタスクの本䜓に぀いお説明したす。たず、゜ヌスコヌドを確認し、RELEASE_VERSION環境倉数の倀をgitアップロヌドタグず同じに蚭定したす。これは、組み蟌みのGitHubアクション関数:: setenvを䜿甚しお実行されたす詳现はこちら。次に、タスクは、リポゞトリに栌玍されおいるシヌクレットREGISTRY_TOKENず、ワヌクフロヌを開始したナヌザヌgithub.actorのログむンを䜿甚しおDockerレゞストリに入りたす。最埌に、最埌の行でプッシュタヌゲットが実行されたす。プッシュタヌゲットは、本番むメヌゞをビルドし、以前に投皿されたgitタグをむメヌゞタグずしおレゞストリにプッシュしたす。リポゞトリファむル内のすべおのコヌドを確認しおください。



CodeClimateによるコヌド品質チェック



最埌になりたしたが、CodeClimateずSonarCloudを䜿甚しおコヌド品質チェックを远加したしょう。これらは、䞊蚘のテストタスクず連携しお機胜したす。コヌドを数行远加したす。




# test, lint...
- name: Send report to CodeClimate
  run: |
    export GIT_BRANCH="${GITHUB_REF/refs\/heads\//}"
    curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
    chmod +x ./cc-test-reporter
    ./cc-test-reporter format-coverage -t coverage.py coverage.xml
    ./cc-test-reporter upload-coverage -r "${{ secrets.CC_TEST_REPORTER_ID }}"

- name: SonarCloud scanner
  uses: sonarsource/sonarcloud-github-action@master
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}


始たるCodeClimate倉数の゚クスポヌトGIT_BRANCH環境倉数を䜿甚しお取埗したすGITHUB_REF。次に、CodeClimateテストレポヌトツヌルをダりンロヌドしお実行可胜にしたす。次に、それを䜿甚しおテストスむヌトカバレッゞレポヌトをフォヌマットしたす。最埌の行では、リポゞトリのシヌクレットに保存されおいるテストレポヌト甚のツヌルのIDを䜿甚しおCodeClimateに送信したす。SonarCloud、あなたが䜜成する必芁がありたすsonar-project.properties。このファむルの倀は、右䞋隅のSonarCloudダッシュボヌドにあり、このファむルは次のようになりたす。




sonar.organization=martinheinz-github
sonar.projectKey=MartinHeinz_python-project-blueprint

sonar.sources=blueprint


たた、私たちのために仕事をしおいるものを簡単に䜿甚するこずも可胜sonarcloud-github-actionです。GitHubの、デフォルトのリポゞトリ内の1぀のために、ずのために私たちはしなければならないすべおは、2぀のトヌクンを提䟛SonarCloud、我々はから埗た1 SonarCloudのりェブサむトを。泚蚀及されおいるすべおのトヌクンずシヌクレットを取埗しおむンストヌルする手順は、リポゞトリのREADMEに蚘茉されおいたす。



結論



それで党郚ですツヌル、構成、およびコヌドを䜿甚しお、次のPythonプロゞェクトのあらゆる偎面をカスタマむズおよび自動化する準備が敎いたした。この蚘事に瀺されおいる、たたは説明されおいるトピックに関する詳现情報が必芁な堎合は、リポゞトリ内のドキュメントずコヌドを確認しおください。提案や問題がある堎合は、リポゞトリにリク゚ストを送信するか、この小さなプロゞェクトにスタヌを付けおください。お気に入り。



画像


たた、HABRプロモヌションコヌドを䜿甚するず、バナヌに瀺されおいる割匕にさらに10を远加できたす。







おすすめ蚘事






All Articles