1Mindocker #13 – با اقدامات GitHub فشار ، بسازید و dockerize کنید

در مقاله آخر ما در مورد CI/CD صحبت کردیم: اما چگونه می توانیم خط لوله CI/CD را در یک چارچوب بدون دردسر و بسیار ساده قرار دهیم؟
خوب ، دیگر نگو! اقدامات GitHub تمام آنچه را که برای تنظیم یک محیط مناسب برای مرتکب -> ساخت -> dockerize برنامه خود دارید ، داشته باشید.
بیایید شیرجه بزنیم!
تنظیم – GitHub
ما چیزی را به صورت اعطا نمی کنیم ، بنابراین فرض کنیم شما یک حساب کاربری GitHub ندارید و شما فقط می خواهید از ابتدا شروع کنید:
- به ثبت نام GitHub بروید و در آنجا با ایمیل و رمز عبور خود ثبت نام کنید. از شما نیز خواسته می شود نام کاربری ایجاد کنید
- فعال کردن 2 عامل احراز هویت (2FA) اختیاری است ، اما توصیه می شود
- پس از ورود به سیستم و راه اندازی ، وقت آن است که اولین مخزن خود را ایجاد کنید!
برای ایجاد مخزن ، به طور کلی باید روی یک کلیک کنید New
یا Create new repository
دکمه سبز: از شما خواسته می شود که دید را انتخاب کنید (اگر repo عمومی یا خصوصی باشد) و نام مخزن. من پیشنهاد می کنم که برای این آموزش ، شما ایجاد کنید مخزن عمومی به نام hello-world-github-docker
بشر
تنظیم – برنامه
حال بیایید یک برنامه کاربردی بسازیم: ما از Python ، یک زبان برنامه نویسی همه کاره استفاده می کنیم که می توانید برای بسیاری از موارد استفاده کنید ، از ساخت برنامه ها گرفته تا تجزیه و تحلیل داده ها ، از ایجاد وب سایت تا یادگیری ماشین.
بیایید اول از همه کلون مخزن GitHub (یعنی یک نسخه محلی از آن) با آن git
(اگر آن را ندارید ، نحوه نصب آن را در اینجا ببینید)
git clone https://github.com/username/hello-world-docker-github
# Remember to change 'username' with your actual username!
cd hello-world-docker-github/
و اکنون ، بیایید ویرایش خود را ایجاد و شروع کنیم app.py
پرونده (.py
پسوند که اسکریپت های پایتون دارند):
touch app.py
code app.py
در touch
دستور پرونده را ایجاد می کند ، در حالی که code
دستور پرونده را در کد Visual Studio باز می کند (یک IDE ، محیط توسعه یکپارچه) برای اصلاح آن. بدیهی است که می توانید از IDE های مختلف استفاده کنید: تا زمانی که برای شما کار کند ، هیچ IDE بهتر از دیگری نیست.
به طور کلی ، برنامه “سلام جهان” چاپ می کند “سلام جهان!” در ترمینال ، مانند این:
print("Hello world!")
اما ما می خواهیم کاری بیشتر انجام دهیم: ما متن سفید وانیلی را در ترمینال خود دوست نداریم ، می خواهیم برخی از 🌈color🌈.
برای انجام این کار ، ما به سادگی باید نصب کنیم termcolor
بسته:
pip install termcolor
اکنون ما فقط آن را وارد اسکریپت خود می کنیم و از آن استفاده می کنیم:
from termcolor import cprint
# cprint stands for "colorer print", and allows us to print colored text
cprint("Hello world!", color="red")
اکنون متن چاپی قرمز خواهد بود ، اما بیایید حتی برخی از ادویه های دیگر را نیز اضافه کنیم ، و به برنامه اجازه می دهیم یک رنگ تصادفی را برای استفاده در چاپ رشته به ترمینال انتخاب کند:
from termcolor import cprint
import random
# random is the library that allows us to extract random items from a list
colors = ["red", "green", "blue", "magenta", "yellow"]
color = random.choice(colors)
cprint("Hello world!", color=color)
اکنون اسکریپت ما به طور تصادفی یکی از رنگ ها را انتخاب می کند و “سلام جهان!” در آن رنگ 🙂
یادداشت:
random
یک کتابخانه داخلی در پایتون است ، به این معنی که در زبان قرار می گیرد: به همین دلیل نیازی به نصب آن نداشتیم.
تنظیم – داکر
خوب ، اکنون ما برنامه خود را داریم: چگونه می توانیم آن را dockerize کنیم؟
اولین گزینه ما می تواند نوشتن یک dockerfile ، ساختن تصویری از آن و فشار دادن آن به Docker Hub باشد. این یک راه حل مناسب است ، اما ما باید هر بار که تغییر در برنامه ایجاد می کنیم ، دوباره تصویر را روی دستگاه محلی خود بسازیم و آن را به سمت Docker Hub سوق دهیم. در حالی که برنامه “Hello World” ما نسبتاً کوچک است و این یک بار برای رایانه ما نخواهد بود ، مطمئناً ما می خواهیم با کاربردهای بزرگتر از این کار جلوگیری کنیم.
راه حل دیگر ، همانطور که گفتیم ، نوشتن Dockerfile ، و سپس بارگذاری برنامه ما در GitHub و اجازه دادن به سکو از ساختمان و فشار دادن تصویر به ghcr
، یعنی رجیستری کانتینر GitHub، رجیستری که تصاویر Docker ساخته شده در Github (همچنین به عنوان شناخته می شود بسته ها) ذخیره می شوند.
از آنجا که هدف ما بهره برداری از اقدامات GitHub است ، بیایید این کار را انجام دهیم!
اولین کاری که باید انجام دهیم ایجاد یک requirements.txt
پرونده ای که تمام وابستگی های لازم را در داخل تصویر Docker ما نصب می کند. در مورد ما ، ما فقط نیاز داریم termcolor
، بنابراین ما فقط می توانیم این کار را انجام دهیم:
- برای ویرایش پرونده ایجاد و باز کنید:
touch requirements.txt
code requirements.txt
- نوشتن
termcolor
بسته در پرونده:
termcolor
حالا بیایید ما را بسازیم Dockerfile
بشر ما می خواهیم تصویر ما حاوی باشد python
، و ما می خواهیم که وابستگی های مورد نیاز را نیز نصب کند ، بنابراین بیایید آن را اینگونه تعریف کنیم:
# Define your python version
ARG PY_VERSION="3.11.9-slim-bookworm"
# Base image
FROM python:${PY_VERSION}
# Define your working directory
WORKDIR /app/
# Copy your local file system into the working directory
COPY ./ /app/
# Install the necessary dependencies
RUN pip cache purge
RUN pip install --no-cache-dir -r requirements.txt
# Run the application as an entrypoint
ENTRYPOINT python3 app.py
اکنون ساختار پوشه محلی ما به این شکل خواهد بود:
.
|__ app.py
|__ requirements.txt
|__ Dockerfile
تنها چیزی که ما به آن نیاز داریم پیکربندی یک فایل گردش کار است که باعث ایجاد اقدامات GitHub می شود و به آنها می گوید که تصویر را بسازند و فشار دهند. برای این کار ، ما می توانیم از الگوی پیش ساخته ارائه شده توسط GitHub استفاده کنیم.
ما باید اول از همه پرونده را ایجاد کنیم:
# The file is placed in a special directory, .github/workflows
mkdir -p .github/workflows
touch .github/workflows/docker-publish.yml
code .github/workflows/docker-publish.yml
همانطور که مشاهده می کنید ، فایل گردش کار با فرمت YAML است ، یک زبان نشانه گذاری قدرتمند که به شما امکان می دهد تمام مراحل مورد نظر خود را در ساخت مشخص کنید. متن زیر را در پرونده ای که اکنون در حال ویرایش هستید کپی و چسباند:
name: Docker
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
schedule:
- cron: '40 8 * * *'
push:
branches: [ "main" ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ "main" ]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as /
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0
with:
cosign-release: 'v2.2.4'
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
اکنون وقت آن است که این گردش کار را آزمایش کنیم!
آزمایش – فشار اول
بیایید اول از همه ، همه تغییرات محلی را به مخزن آنلاین اضافه کنیم ، مرتکب و فشار دهیم:
git add .
git commit -m "first commit"
git branch -M main
git push -u origin main
از شما خواسته می شود نام کاربری و رمز عبور GitHub خود را وارد کنید. به عنوان رمز عبور ، شما باید از یک نشانه دسترسی GitHub استفاده کنید ، که می توانید در اینجا ایجاد کنید.
پس از تغییر تغییر ، شما می بینید ، در repo github آنلاین خود ، یک نقطه قهوه ای: این بدان معنی است که گردش کاری که با فشار ما ایجاد کرده ایم اکنون کار می کند و تصویر را می سازد و فشار می آورد. اگر گردش کار موفقیت آمیز باشد ، در انتهای آن یک کنه سبز مشاهده خواهید کرد ، در حالی که اگر شکست بخورد ، یک صلیب سرخ را خواهید دید.
اطمینان حاصل کنید که پس از ایجاد بسته ، آن است عمومی: اگر اینطور نیست ، دید خود را به عموم تغییر دهید ، در غیر این صورت نمی توانید آن را بارگیری کنید.
آزمایش – تلاش برای برنامه ما
همانطور که گفتیم ، تصویر Docker به عنوان بسته زیر بارگذاری می شود ghcr.io
؛ سپس می توانیم تصویر را مانند این بکشید و اجرا کنیم:
docker pull ghcr.io/username/hello-world-github-docker:main
docker run -t ghcr.io/username/hello-world-github-docker:main
اگر Docker می گوید که نمی تواند تصویر را بکشد زیرا شما وارد رجیستری Container GitHub نشده اید ، می توانید به سادگی اجرا کنید:
docker login ghcr.io -u username -p GITHUB-ACCESS-TOKEN
و این باید جادو را انجام دهد!
وقتی برنامه خود را اجرا کردیم ، باید یک رنگ “سلام جهان!” چاپ شده روی ترمینال.
اصلاح برنامه ما
حال ، بیایید بگوییم که ما می خواهیم به کاربر اجازه دهیم رنگی را که می خواهد “سلام جهان” با آن چاپ کند ، انتخاب کند. ما می توانیم خود را اصلاح کنیم app.py
مثل این:
from termcolor import cprint
colors = ["red", "green", "blue", "magenta", "yellow"]
# Tell the user the instructions
print(f"Hello user! What color would you like 'Hello world' to be printed with?\nChoose among: {', '.join(colors)}")
# Take the input from the user
color = input("-->")
# Check if the input is in the available colors: if not, tell the user that it is not available
if color.lower() in colors:
cprint("Hello world!", color=color)
else:
print("ERROR! The color you chose is not among the available colors :(")
برای اصلاح تصویر Docker ، اکنون اضافه کردن ، تعهد و فشار آوردن تغییرات محلی به repo آنلاین کافی است:
git add .
git commit -m "user defined color"
git push origin main
اگر گردش کار دوباره موفقیت آمیز باشد ، ما باید بتوانیم تصویر جدید را با ویژگی های به روز شده بکشید و اجرا کنیم:
docker pull ghcr.io/username/hello-world-github-docker:main
docker run -it ghcr.io/username/hello-world-github-docker:main
ما برای این مقاله در اینجا متوقف خواهیم شد ، اما در مورد بعدی ، ما با استفاده از Docker برای استقرار در ابرهای مختلف استفاده خواهیم کرد: با ما همراه باشید و از آن لذت ببرید!