
ãã¼ã¿ã¨ã³ã¸ãã¢ã®@masaki925 ã§ãã
ç§ãæå±ãããã¼ã¿çµç¹ã§ã¯ãã¹ã¿ãã£ãµããªæ¬ä½ã«å¯¾ãã¦æ¤ç´¢ãã¬ã³ã¡ã³ããªã©ã®ãã¼ã¿ãããã¯ãããã¤ã¯ããµã¼ãã¹ã¨ãã¦æä¾ãã¦ããããã®å¤ãã¯Python ãã¡ã¤ã³è¨èªã§ãã
ã¾ããã¼ã¿åºç¤ã¨ãã¦BigQuery ãã¯ããã¨ããGCP ãµã¼ãã¹ãå¤ãæ´»ç¨ãã¦ãã¾ãã
ç¾å¨ãç§ã¯2020å¹´é ããæ°è¦ããã¸ã§ã¯ãã«åç»ãã¦ãããããã§ãPython ã¨GCP ããã¼ã¹ã¨ããéçºç°å¢ãæ§ç¯ãã¾ããã
ç§ãéçºç°å¢ã«æ±ãããã¨ã¯ãTDD ããããããã¨ãã§ãã
ããã¯å¹³ããè¨ãã¨ããã¹ããæ¸ãã¦ãå®è£ ãã¦ãCI/CD ãã¦ãã¨ãããµã¤ã¯ã«ãå¹ççã«åããã¨ã§ããå½ããåã®ãã¨ãå½ããåã«ããããããã ããã ãã§ãã
ä»åã以ä¸ã®ç°å¢ã§ããããããã¨ãããããã¤ãç½ ããã£ãã®ã§è¨ãã¦ããã¾ãã
$ docker compose run poetry-docker-build-and-run python -V Python 3.9.9 $ docker compose run poetry-docker-build-and-run poetry -V Poetry version 1.1.12 $ docker -v Docker version 20.10.10, build b485636 $ docker run gcr.io/cloud-builders/docker -v Docker version 19.03.9, build 9d988398e7 Cloud Build (2021-12-01 æç¹) Cloud Run (2021-12-01 æç¹)
TL;DR
ä»åæ§ç¯ããç°å¢ã®ã¨ãã»ã³ã¹ãçãè¾¼ãã ãµã³ãã«ããã¸ã§ã¯ããç½®ãã¦ããã¾ããã
ãããããã¨
å ¨ä½çã«æ®éã ã¨æãã¾ãããã¨ããã©ããç½ ãããã®ã§ãããã¯ã¢ãã(â å°) ãã¦å¾è¿°ãã¦ããã¾ãã
Python ããã±ã¼ã¸ç®¡ç
- => Poetry ã®å©ç¨
- ä»ã®ä¸»è¦ãã¼ã«ã¨ã®æ¯è¼ã¯ãã¡ãã®è¨äºã大å¤åèã«ãªãã¾ã: vaaaaaanquish.hatenablog.com
éçºç°å¢ã®ã³ã³ããå
- => Docker, Docker Compose ã®å©ç¨
- æè¿ã¯Codespaces ãªã©ãçãä¸ãããè¦ãã¦ãã¾ãããä»åã¯æ¤è¨ãã¦ãã¾ãã (彿èããããªãã£ã)
live reload, testing
- è¦ã¯ã³ã¼ãã®å¤æ´ãå³åº§ã«ç¢ºèªã§ãããã¨
- server ãreload ãããã¨ãªã夿´ã確èª
- container ãrebuild ãããã¨ãªããã¹ãã宿½
- => Docker volume mount ã®å©ç¨
- â
1
- Poetry ã®virtualenvs.in-project ã¯true ã«ããªã
- => ããããvirtualenvs.create ãfalse ã«ãã
- Poetry ã®virtualenvs.in-project ã¯true ã«ããªã
- è¦ã¯ã³ã¼ãã®å¤æ´ãå³åº§ã«ç¢ºèªã§ãããã¨
CI/CD
- push ãããCI ãèµ°ã
- ãã¹ããéã£ãããã¼ã¸å¯è½
- ãã¼ã¸ããããããã¤ããã
- => Cloud Build ã®å©ç¨
ç¡éPR ç°å¢ (â 2)
- PR (= Pull Request) ã使ããæç¹ã§æå確èªããããã«ãããã¤ãããç°å¢
- (ããã¯ç¤¾å äºæ ã«ãããã®ã ã) æ¢åã®ç¤¾å ã¤ã³ãã©åºç¤(AWS) ã§ã¯åãã¦ããæ©è½ã ã£ãããGCP ã§åç´ã«Cloud Run ãå©ç¨ããã ãã§ã¯ä½¿ããªããªã£ã¦ãã¾ã£ã
- => Cloud Build Trigger ã®å©ç¨ (使ãåã)
ãã«ãã®å¹çå
- é«éåããã£ã¹ã¯å®¹éç¯ç´ã®ãã
- => Docker multi-stage builds, build cache ã®å©ç¨
- â
3
- Cloud Build ãé¢ä¿ãªãstage ãskip ãã¦ãããªã
Dockerfile+ ã®include ææ³ ã使ãããã使ããªãä»åã¯ä¸è¦ã«ãªã£ã
- =>
Dockerfile, cloudbuild.yaml ãåããBuildKitãæå¹ã«ãã
- Cloud Build ãé¢ä¿ãªãstage ãskip ãã¦ãããªã
Poetry ã®virtualenvs.in-project ã¯true ã«ããªã
ããã£ã¦ãã¾ãã°åç´ãªè©±ã§ãããçè ã¯ç¡é§ã«ããã£ã¦ãã¾ãã¾ããã
ã¨ããã®ãããpoetry docker best practiceãã§æ¤ç´¢ããã¨ä¸ä½ã«ãããããpython-poetry-docker-example ã¨ãããªãã¸ããªãããã
ããã§ã¯ POETRY_VIRTUALENVS_IN_PROJECT=true ãå
¥ã£ã¦ãã¾ãã
ãã®ãªãã·ã§ã³ã使ãã¨ãpoetry install ãåæã«ã«ã¬ã³ããã£ã¬ã¯ããªã« .venv ãã£ã¬ã¯ããªã使ããvirtualenv ã¨ãã¦å©ç¨ãã¾ãã
ã¾ãPoetry ã¯ããã©ã«ãã§.venv ãåå¨ããå ´åããããvirtualenv ã¨ãã¦å©ç¨ãã¾ãã
ãã®çµæãvolume mount ããç¶æ
ã ã¨ããã¹ãå´ã¨ã³ã³ããå´ã§.venv ãå
±æããã¦ãã¾ããæå³ããªãæå(ã¤ã³ã¹ãã¼ã«ãããã®ãããã¦ããªãã£ãããéã ã£ãã) ããã¾ãã
ããã«æ··ä¹±ããã®ã¯ãvenv ã®path ãæå®ã§ããªãã®ãã¨ããè°è«ããããä½è ããã®æ©è½ãæå¦ãã¦ãããããwork around ãªã©ãææ¡ããã¦ãã¾ãã
ã§ãããããããã³ã³ããå ã§virtualenv ã使ããªããã°ä¸è¦ãªè°è«ãªã®ã§ããã£ãã¨virtualenv.create false ãã¦ãã¾ãã¾ãããã
ç¡éPR ç°å¢
è¦ä»¶ã¯ä¸è¨ã§ãã
- Pull Requst ãä½ãããã¨ãã«ãå°ç¨ã®ãµã¼ãã¹(Cloud Run instance) ããããã¤ããã
- ãµã¼ãã¹ã®ååã«
pr-(PR çªå·)ãä»ä¸ããã¦ãã) - PR ããã¼ã¸ããããã main ç°å¢ (dev ãprod ) ã«ãããã¤ããã
ãããã¯ã¹ã¿ãã£ãµããªãã¡ã¤ã³ã§å©ç¨ãã¦ããã¤ã³ãã©åºç¤(AWS) ã§ã¯æ¢ã«SRE ãã¼ã ã«ãã£ã¦å®ç¾ããã¦ãããä»ã¾ã§ç¹ã«æ°ã«ããå¿ è¦ãããã¾ããã§ããã
ä»åã¡ã¤ã³åºç¤ã§ã¯ãªãGCP ã®ã¿ã§å®çµããæ§æãåã£ãçµæããã®ä¾¿å©æ©è½ã使ããªããªã£ã¦ãã¾ãããã£ã±ããã£ãã»ãããããããã¨ãªã£ã次第ã§ãã
å®ç¾æ¹æ³ã¨ãã¦ãCloud Build ã®Trigger ã2ã¤ä½¿ãåãã¦ãã¾ãã
Terraform ã®ãªã½ã¼ã¹google_cloudbuild_trigger ã®github.pull_request 㨠github.push ã«ãããè¨å®ã使ãåãããã¨ã§ãPR ãåºãããã¨ãã¨ãã¼ã¸ãããã¨ããåºå¥ãã¦ãã¾ãã
ã¾ãcloudbuil.yaml ã®deploy ã³ãã³ãã§æå®ããååã ${_APP_NAME}-${_ENV}${_PR_NUMBER} ã¨ãã¦ããpull ãªã¯ã¨ã¹ã ããªã¬ã¼ã«ä½¿ç¨ãã GitHub åºæã®ããã©ã«ãã®ç½®æããå©ç¨ãã¦PR çªå·ãåå¾ãã¦ãã¾ãã
ããã«ãã£ã¦ç¡äºPR ç°å¢ãåãæ»ããã¨ãã§ãã¾ããã
ãããæ®èª²é¡ã¨ãã¦ããã¼ã¸å¾ã«æ®ã£ãPR ç°å¢ããã®ã¾ã¾æ¾ç½®ããã¦ãã¾ãã¨ããåé¡ãããã¾ãã
ãã¤ã¼ãã«ã¯å®æçã«ãæé¤ããããæµããªã©ããã¾ãããon-demand ã«èªè¨¼æ å ±(ä¾ãã°GCP -> GitHub) ãæããã«æ¸ã¾ããæ¹æ³ãç¡ãããªã¨æ¨¡ç´¢ãã¦ãã¾ãã
(åè¿°ã®ãã¼ã¸æã®github.push ããªã¬ã¼ã§ã¯_PR_NUMBER ãåããªãããåãæ¹æ³ã§ã¯ã§ããªã)
ããæ¹æ³ãããã°ãã²æãã¦ããã ããã¨ããããã§ãã
Cloud Build ãé¢ä¿ãªãstage ãskip ãã¦ãããªã
Docker ã®multi-stage builds ã®è©±ã§ãã
ä¾ãã°
FROM alpine as base FROM base as step1 RUN echo step1 FROM base as step2 RUN echo step2
ããã£ãã¨ãã local ã§ã®å®è¡ã¨ãCloud Build ã«ããå®è¡ã§ã¯æåãç°ãªãã¾ãã
local ã ã¨(æçµææç©ã¨ãã¦å¿ è¦ãª) step2 ã®ã¿å®è¡ããã
$ d build -t aaa . [+] Building 2.0s (6/6) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 36B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/alpine:latest 1.9s => [base 1/1] FROM docker.io/library/alpine@sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300 0.0s => CACHED [step2 1/1] RUN echo step2 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:b62cafe42d4621e2b4bfb8282b741fb23a5303471273f9655be85e4ad8fc579e 0.0s => => naming to docker.io/library/aaa 0.0s
Cloud Build ã ã¨ä¸¡æ¹å®è¡ããã
# cloudbuild.yaml steps: - name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'aaa', '.']
$ gcloud builds submit --config cloudbuild.yaml (... snip) BUILD Already have image (with digest): gcr.io/cloud-builders/docker Sending build context to Docker daemon 34.3kB Step 1/5 : FROM alpine as base latest: Pulling from library/alpine 59bf1c3509f3: Pulling fs layer 59bf1c3509f3: Verifying Checksum 59bf1c3509f3: Download complete 59bf1c3509f3: Pull complete Digest: sha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300 Status: Downloaded newer image for alpine:latest ---> c059bfaa849c Step 2/5 : FROM base as step1 ---> c059bfaa849c Step 3/5 : RUN echo step1 ---> Running in 89c951160e32 step1 Removing intermediate container 89c951160e32 ---> aa33d769764c Step 4/5 : FROM base as step2 ---> c059bfaa849c Step 5/5 : RUN echo step2 ---> Running in 011188bcff62 step2 Removing intermediate container 011188bcff62 ---> b46331031f63 Successfully built b46331031f63 Successfully tagged aaa:latest PUSH DONE
ããã«ãããä¾ãã°ãPR ç°å¢ã§ã¯ãã¹ããå®è¡ãã¦ãããããã¤ããããããã¼ã¸å¾ã¯ç´æ¥main ç°å¢ã«ãããã¤ããå ´åãã«ã両ç°å¢ã§åãDockerfile ã使ã£ã¦ããã¨ããããã¤æã«ä½è¨ãªstage ãå®è¡ããããã¨ã«ãªãããããã¤æéãé·ããªã£ã¦ãã¾ãã¾ãã
(以ä¸ãç·¨éããã2021-12-08)
ãã®ãããDockerfile, cloudbuild.yaml ãããããPR ç°å¢ç¨ã¨main ç°å¢ç¨ã§ä½¿ãåãã¦ãã¾ãã => å¾è¿°ã®éããä¸è¦ã«ãªãã¾ããã
ãã®åå ã«ã¤ãã¦ã¯ã
ããããCloud Build ãµã¼ãã¹ã¨ããããã¯step ã§æå®ãã¦ããCloud Builder ã®docker ã¤ã¡ã¼ã¸ã«ããå¶ç´ãªæ°ããã¾ããã詳細ã¯ããã£ã¦ããªãããããªã«ããåç¥ã®æ¹ããããæãã¦ããã ããã¨ããããã§ãã
親åãªæ¹ã«æãã¦ããã ãã¾ããããããã¨ããããã¾ãã
ãã®è¨äºã«æ¸ããã¦ãã `Cloud Build ãé¢ä¿ãªãstage ãskip ãã¦ãããªã` ã¯BuildKitãæå¹ã«ãªã£ã¦ãããã©ãããåé¡ã ã¨æãã¾ãã https://t.co/lmJSobd5OU ããã«ãã解決çã®éãç°å¢å¤æ°ã«DOCKER_BUILDKIT=1ã追å ããã¨è§£æ±ºããã¨æãã¾ã
— ãããã® (@orisano) 2021å¹´12æ7æ¥
試ãã«ç°å¢å¤æ°ã追å ãã¦ã¿ãã¨ãããæå³éãskip ããã¾ããã
# cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-f', 'Dockerfile.ext', '-t', 'gcr.io/$PROJECT_ID/aaa', '.']
+ env:
+ - "DOCKER_BUILDKIT=1"
$ gcloud builds submit --config cloudbuild.yaml (...snip) BUILD Already have image (with digest): gcr.io/cloud-builders/docker #1 [internal] load build definition from Dockerfile #1 transferring dockerfile: 129B done #1 DONE 0.1s #2 [internal] load .dockerignore #2 transferring context: 2B done #2 DONE 0.0s #3 [internal] load metadata for docker.io/library/alpine:latest #3 DONE 0.3s #4 [base 1/1] FROM docker.io/library/alpine@sha256:21a3deaa0d32a8057914f365... #4 DONE 0.0s #5 [step2 1/1] RUN echo step2 #5 0.258 step2 #5 DONE 0.3s #6 exporting to image #6 exporting layers #6 exporting layers 0.0s done #6 writing image sha256:296579c9f857070089c03611667b890aa787eb5c71b03e2bb8aa137b8473e54e done #6 naming to gcr.io/iwa-lab/aaa done #6 DONE 0.1s PUSH DONE
ããè¦ãã¨åºåå½¢å¼ãå¤ãã£ã¦ãããbuilder ãBuildKit ã«åãæ¿ãã£ã¦ãããã¨ããããã¾ãã
ã¾ããDockerfile+ ã®include ææ³ ãBuildKit ãæå¹ã«ãããã¨ã§ä½¿ããããã«ãªãã¾ããã(ä»åã®ç¨éã§ã¯Dockerfile ãåããå¿ è¦ããªããªãã¾ããããåå ãããã£ã¦ããã£ãã)
ãBuildKit... ãåã ã£ãã®ã...ã
ã¨ãããã¨ã§ãCloud Build ã§multi-sage ã®skip ãå©ç¨ãããå ´åã¯BuildKit ãæå¹ã«ãã¦ããã¾ãããã
(ç·¨éããã¾ã§ã2021-12-08)
ãã¾ã
- Poetry ã®project name ã«
-ã使ãã¨ãmodule åã¯_ã«å¤æããããããmodule not foundã®åå ã«ãªã£ãããã - Poetry install ã³ãã³ãã¯ããã©ã«ãã§root project ãmodule ã¨ãã¦install ãã¦ãããããDockerfile ã®cache ã®èª¿æ´ã§COPY src ãããåã«poetry install ã¨ããã¦ããããã¨module ã¯install ãããªã (å½ããåã ãã©)
ã¾ã¨ã
ãã®ããã«ããã¤ãã®ç½ ã«è¶³ãåãããªããããçè ã®èãããTDD ãããããPython éçºç°å¢ãæ´ãããã¨ãã§ãã¾ããã
ãã®ãããããã(ãã¡ããã¡ã³ãã¼ã®è½åã«ããã¨ãããããã¾ãã)ãããã¸ã§ã¯ãã«æ°ããåç»ããã¡ã³ãã¼ã®ç«ã¡ä¸ããããããã¹ã ã¼ãºã«ç°å¢æ§ç¯ãæ¸ã¾ããgood first issue ãçéã§ããªãã¦ããã£ãããã¦ãã¾ãã

ãããããå½ããåã®ãã¨ãå½ããåã«ããªãã¤ã¤ããµã¼ãã¹ã®æ¹åã«åªãã¦ããããã¨æãã¾ãã
ç§ãã¡ã¯ããã¼ã¿ã®åã§æªæ¥ã®æè²ã»å¦ã³ãåµãåºãã¦ããããã¨ããæ¹ãçµ¶è³åéä¸ã§ãããèå³ããæ¹ã¯ãã²ä»¥ä¸ã®æ¡ç¨ãã¼ã¸ãããå¿åãã ããã