ื”ืจื›ื‘ื” ื•ืคืจื™ืกื” ื“ื™ื ืžื™ืช ืฉืœ ืชืžื•ื ื•ืช Docker ืขื werf ื‘ืืžืฆืขื•ืช ื“ื•ื’ืžื” ืฉืœ ืืชืจ ืชื™ืขื•ื“ ื’ืจืกื”

ื›ื‘ืจ ื“ื™ื‘ืจื ื• ืขืœ ื›ืœื™ GitOps ืฉืœื ื• ื™ื•ืชืจ ืžืคืขื ืื—ืช. werf, ื•ื”ืคืขื ื‘ืจืฆื•ื ื ื• ืœื—ืœื•ืง ืืช ื”ื ื™ืกื™ื•ืŸ ืฉืœื ื• ื‘ื”ืจื›ื‘ืช ื”ืืชืจ ืขื ื”ืชื™ืขื•ื“ ืฉืœ ื”ืคืจื•ื™ืงื˜ ืขืฆืžื• - werf.io (ื”ื’ืจืกื” ื”ืจื•ืกื™ืช ืฉืœื• ื”ื™ื en.werf.io). ื–ื”ื• ืืชืจ ืกื˜ื˜ื™ ืจื’ื™ืœ, ืื‘ืœ ื”ื”ืจื›ื‘ื” ืฉืœื• ืžืขื ื™ื™ื ืช ื‘ื›ืš ืฉื”ื•ื ื‘ื ื•ื™ ื‘ืืžืฆืขื•ืช ืžืกืคืจ ื“ื™ื ืžื™ ืฉืœ ื—ืคืฆื™ื.

ื”ืจื›ื‘ื” ื•ืคืจื™ืกื” ื“ื™ื ืžื™ืช ืฉืœ ืชืžื•ื ื•ืช Docker ืขื werf ื‘ืืžืฆืขื•ืช ื“ื•ื’ืžื” ืฉืœ ืืชืจ ืชื™ืขื•ื“ ื’ืจืกื”

ื”ื™ื›ื ืกื• ืœื ื™ื•ืื ืกื™ื ืฉืœ ืžื‘ื ื” ื”ืืชืจ: ื™ืฆื™ืจืช ืชืคืจื™ื˜ ืžืฉื•ืชืฃ ืœื›ืœ ื”ื’ืจืกืื•ืช, ื“ืคื™ื ืขื ืžื™ื“ืข ืขืœ ืžื”ื“ื•ืจื•ืช ื•ื›ื•'. - ืื ื—ื ื• ืœื. ื‘ืžืงื•ื ื–ืืช, ื‘ื•ืื• ื ืชืžืงื“ ื‘ื ื•ืฉืื™ื ื•ื‘ืžืืคื™ื™ื ื™ื ืฉืœ ื”ืจื›ื‘ื” ื“ื™ื ืžื™ืช ื•ืงืฆืช ื‘ืชื”ืœื™ื›ื™ ื”-CI/CD ื”ื ืœื•ื•ื™ื.

ืžื‘ื•ื: ืื™ืš ื”ืืชืจ ืขื•ื‘ื“

ืžืœื›ืชื—ื™ืœื”, ืชื™ืขื•ื“ werf ืžืื•ื—ืกืŸ ื™ื—ื“ ืขื ื”ืงื•ื“ ืฉืœื•. ื–ื” ืžื˜ื™ืœ ื“ืจื™ืฉื•ืช ืคื™ืชื•ื— ืžืกื•ื™ืžื•ืช ืฉื”ืŸ ื‘ื“ืจืš ื›ืœืœ ืžืขื‘ืจ ืœืชื—ื•ื ืฉืœ ืžืืžืจ ื–ื”, ืืš ืœื›ืœ ื”ืคื—ื•ืช ื ื™ืชืŸ ืœื•ืžืจ ื›ื™:

  • ืื™ืŸ ืœืฉื—ืจืจ ืคื•ื ืงืฆื™ื•ืช werf ื—ื“ืฉื•ืช ืœืœื ืขื“ื›ื•ืŸ ื”ืชื™ืขื•ื“, ื•ืœื”ืคืš, ื›ืœ ืฉื™ื ื•ื™ ื‘ืชื™ืขื•ื“ ืžืจืžื– ืขืœ ืฉื—ืจื•ืจ ื’ืจืกื” ื—ื“ืฉื” ืฉืœ werf;
  • ืœืคืจื•ื™ืงื˜ ื™ืฉ ืคื™ืชื•ื— ืื™ื ื˜ื ืกื™ื‘ื™ ืœืžื“ื™: ื ื™ืชืŸ ืœืฉื—ืจืจ ื’ืจืกืื•ืช ื—ื“ืฉื•ืช ืžืกืคืจ ืคืขืžื™ื ื‘ื™ื•ื;
  • ื›ืœ ืคืขื•ืœื” ื™ื“ื ื™ืช ืœืคืจื™ืกืช ืืชืจ ืขื ื’ืจืกื” ื—ื“ืฉื” ืฉืœ ืชื™ืขื•ื“ ื”ื™ื ืœืคื—ื•ืช ืžื™ื™ื’ืขืช;
  • ื”ืคืจื•ื™ืงื˜ ื ื•ืงื˜ ื‘ื’ื™ืฉื” ืกืžื ื˜ื™ืช ื ื™ื”ื•ืœ ื’ืจืกืื•ืช, ืขื 5 ืขืจื•ืฆื™ ื™ืฆื™ื‘ื•ืช. ืชื”ืœื™ืš ื”ืฉื—ืจื•ืจ ื›ื•ืœืœ ืžืขื‘ืจ ืจืฆื™ืฃ ืฉืœ ื’ืจืกืื•ืช ื‘ืขืจื•ืฆื™ื ืœืคื™ ืกื“ืจ ื”ื’ื‘ืจืช ื”ื™ืฆื™ื‘ื•ืช: ืžืืœืคื ืœืžื•ืฆืง ืกืœืข;
  • ืœืืชืจ ื™ืฉ ื’ืจืกื” ื‘ืฉืคื” ื”ืจื•ืกื™ืช, ืฉ"ื—ื™ื” ื•ืžืชืคืชื—ืช" (ื›ืœื•ืžืจ, ืชื•ื›ื ื” ืžืชืขื“ื›ืŸ) ื‘ืžืงื‘ื™ืœ ืœื’ืจืกื” ื”ืจืืฉื™ืช (ื›ืœื•ืžืจ, ื‘ืื ื’ืœื™ืช).

ื›ื“ื™ ืœื”ืกืชื™ืจ ืืช ื›ืœ ื”"ืžื˜ื‘ื— ื”ืคื ื™ืžื™" ื”ื–ื” ืžื”ืžืฉืชืžืฉ, ืœื”ืฆื™ืข ืœื• ืžืฉื”ื• ืฉ"ืคืฉื•ื˜ ืขื•ื‘ื“", ืขืฉื™ื ื• ื›ืœื™ ื”ืชืงื ื” ื•ืขื“ื›ื•ืŸ ื ืคืจื“ ืฉืœ werf - ื”ืื multiwerf. ืืชื” ืจืง ืฆืจื™ืš ืœืฆื™ื™ืŸ ืืช ืžืกืคืจ ื”ืฉื—ืจื•ืจ ื•ืืช ืขืจื•ืฅ ื”ื™ืฆื™ื‘ื•ืช ืฉื‘ื• ืืชื” ืžื•ื›ืŸ ืœื”ืฉืชืžืฉ, ื•-multiwerf ื™ื‘ื“ื•ืง ืื ื™ืฉ ื’ืจืกื” ื—ื“ืฉื” ื‘ืขืจื•ืฅ ื•ืชื•ืจื™ื“ ืื•ืชื” ื‘ืžื™ื“ืช ื”ืฆื•ืจืš.

ื‘ืชืคืจื™ื˜ ื‘ื—ื™ืจืช ื”ื’ืจืกื” ื‘ืืชืจ, ื”ื’ืจืกืื•ืช ื”ืขื“ื›ื ื™ื•ืช ื‘ื™ื•ืชืจ ืฉืœ werf ื–ืžื™ื ื•ืช ื‘ื›ืœ ืขืจื•ืฅ. ื›ื‘ืจื™ืจืช ืžื—ื“ืœ, ืœืคื™ ื›ืชื•ื‘ืช werf.io/documentation ื”ื’ืจืกื” ืฉืœ ื”ืขืจื•ืฅ ื”ื™ืฆื™ื‘ ื‘ื™ื•ืชืจ ืขื‘ื•ืจ ื”ืžื”ื“ื•ืจื” ื”ืื—ืจื•ื ื” ื ืคืชื—ืช - ื”ื™ื ื’ื ืžืชื•ื•ืกืคืช ืœืื™ื ื“ืงืก ืขืœ ื™ื“ื™ ืžื ื•ืขื™ ื”ื—ื™ืคื•ืฉ. ืชื™ืขื•ื“ ืœืขืจื•ืฅ ื–ืžื™ืŸ ื‘ื›ืชื•ื‘ื•ืช ื ืคืจื“ื•ืช (ืœื“ื•ื’ืžื”, werf.io/v1.0-beta/documentation ืขื‘ื•ืจ ืžื”ื“ื•ืจืช ื‘ื˜ื 1.0).

ื‘ืกืš ื”ื›ืœ, ื‘ืืชืจ ื–ืžื™ื ื•ืช ื”ื’ืจืกืื•ืช ื”ื‘ืื•ืช:

  1. root (ื ืคืชื— ื›ื‘ืจื™ืจืช ืžื—ื“ืœ),
  2. ืขื‘ื•ืจ ื›ืœ ืขืจื•ืฅ ืขื“ื›ื•ืŸ ืคืขื™ืœ ืฉืœ ื›ืœ ืžื”ื“ื•ืจื” (ืœื“ื•ื’ืžื”, werf.io/v1.0-beta).

ื›ื“ื™ ืœื™ืฆื•ืจ ื’ืจืกื” ืกืคืฆื™ืคื™ืช ืฉืœ ืืชืจ, ื‘ืื•ืคืŸ ื›ืœืœื™, ื–ื” ืžืกืคื™ืง ื›ื“ื™ ืœื”ืจื›ื™ื‘ ืื•ืชื• ื‘ืืžืฆืขื•ืช ื’'ืงื™ืœืขืœ ื™ื“ื™ ืจื™ืฆื” ื‘ืกืคืจื™ื™ื” /docs ืคืงื•ื“ื” ืžืชืื™ืžื” ืœืžืื’ืจ werf (jekyll build), ืœืื—ืจ ืžืขื‘ืจ ืœืชื’ Git ืฉืœ ื”ื’ืจืกื” ื”ื ื“ืจืฉืช.

ื ื•ืชืจ ืจืง ืœื”ื•ืกื™ืฃ ื›ื™:

  • ื›ืœื™ ื”ืฉื™ืจื•ืช ืขืฆืžื• (werf) ืžืฉืžืฉ ืœื”ืจื›ื‘ื”;
  • ืชื”ืœื™ื›ื™ CI/CD ื‘ื ื•ื™ื™ื ืขืœ ื‘ืกื™ืก GitLab CI;
  • ื•ื›ืœ ื–ื”, ื›ืžื•ื‘ืŸ, ืคื•ืขืœ ื‘-Kubernetes.

ืžืฉื™ืžื•ืช

ืขื›ืฉื™ื• ื‘ื•ืื• ื ื ืกื— ืžืฉื™ืžื•ืช ื”ืœื•ืงื—ื•ืช ื‘ื—ืฉื‘ื•ืŸ ืืช ื›ืœ ื”ืคืจื˜ื™ื ื”ืžืชื•ืืจื™ื:

  1. ืœืื—ืจ ืฉื™ื ื•ื™ ื’ืจืกืช werf ื‘ื›ืœ ืขืจื•ืฅ ืขื“ื›ื•ืŸ ื™ืฉ ืœืขื“ื›ืŸ ืืช ื”ืชื™ืขื•ื“ ื‘ืืชืจ ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™.
  2. ื‘ืฉื‘ื™ืœ ื”ืชืคืชื—ื•ืช ืืชื” ืฆืจื™ืš ืœื”ื™ื•ืช ืžืกื•ื’ืœ ืœืคืขืžื™ื ืœื”ืฆื™ื’ ื’ืจืกืื•ืช ืชืฆื•ื’ื” ืžืงื“ื™ืžื” ืฉืœ ื”ืืชืจ.

ื™ืฉ ืœื‘ืฆืข ืงื•ืžืคื™ืœืฆื™ื” ืžื—ื“ืฉ ืฉืœ ื”ืืชืจ ืœืื—ืจ ืฉื™ื ื•ื™ ื”ื’ืจืกื” ื‘ื›ืœ ืขืจื•ืฅ ืžืชื’ื™ื•ืช Git ื”ืžืชืื™ืžื•ืช, ืืš ื‘ืชื”ืœื™ืš ื‘ื ื™ื™ืช ื”ืชืžื•ื ื” ื ืงื‘ืœ ืืช ื”ืคื™ืฆ'ืจื™ื ื”ื‘ืื™ื:

  • ืžื›ื™ื•ื•ืŸ ืฉืจืฉื™ืžืช ื”ื’ืจืกืื•ืช ื‘ืขืจื•ืฆื™ื ืžืฉืชื ื”, ื™ืฉ ืฆื•ืจืš ืœื‘ื ื•ืช ืžื—ื“ืฉ ืืช ื”ืชื™ืขื•ื“ ืจืง ืœืขืจื•ืฆื™ื ืฉื‘ื”ื ื”ื’ืจืกื” ื”ืฉืชื ืชื”. ืื—ืจื™ ื”ื›ืœ, ืœื‘ื ื•ืช ื”ื›ืœ ืžื—ื“ืฉ ื–ื” ืœื ืžืื•ื“ ื ื—ืžื“.
  • ืขืจื›ืช ื”ืขืจื•ืฆื™ื ืœื”ืคืฆื•ืช ืขืฉื•ื™ื” ืœื”ืฉืชื ื•ืช. ื‘ืฉืœื‘ ืžืกื•ื™ื ื‘ื–ืžืŸ, ืœืžืฉืœ, ื™ื™ืชื›ืŸ ืฉืœื ืชื”ื™ื” ื‘ืขืจื•ืฆื™ื ื’ืจืกื” ื™ืฆื™ื‘ื” ื™ื•ืชืจ ืžื”ื’ืจืกื” 1.1 ืขื ื’ื™ืฉื” ืžื•ืงื“ืžืช, ืื‘ืœ ืขื ื”ื–ืžืŸ ื”ืŸ ื™ื•ืคื™ืขื• - ื‘ืžืงืจื” ื–ื”, ื”ืื ืœื ื›ื“ืื™ ืœืฉื ื•ืช ืืช ื”ืžื›ืœื•ืœ ื‘ืื•ืคืŸ ื™ื“ื ื™?

ืžืชื‘ืจืจ ื›ื™ ื”ืจื›ื‘ื” ืชืœื•ื™ื” ื‘ืฉื™ื ื•ื™ ื ืชื•ื ื™ื ื—ื™ืฆื•ื ื™ื™ื.

ะ ะตะฐะปะธะทะฐั†ะธั

ื‘ื—ื™ืจืช ื’ื™ืฉื”

ืœื—ืœื•ืคื™ืŸ, ืชื•ื›ืœ ืœื”ืจื™ืฅ ื›ืœ ื’ืจืกื” ื ื“ืจืฉืช ื›ืคื•ื“ ื ืคืจื“ ื‘-Kubernetes. ืืคืฉืจื•ืช ื–ื• ืžืจืžื–ืช ืขืœ ืžืกืคืจ ื’ื“ื•ืœ ื™ื•ืชืจ ืฉืœ ืื•ื‘ื™ื™ืงื˜ื™ื ื‘ืืฉื›ื•ืœ, ืฉื™ื’ื“ืœ ืขื ื”ื’ื™ื“ื•ืœ ื‘ืžืกืคืจ ืฉื—ืจื•ืจื™ ื”-werf ื”ื™ืฆื™ื‘ื™ื. ื•ื–ื”, ื‘ืชื•ืจื•, ืžืจืžื– ืขืœ ืชื—ื–ื•ืงื” ืžื•ืจื›ื‘ืช ื™ื•ืชืจ: ืœื›ืœ ื’ืจืกื” ื™ืฉ ืฉืจืช HTTP ืžืฉืœื”, ื•ืขื ืขื•ืžืก ืงื˜ืŸ. ื›ืžื•ื‘ืŸ ืฉื–ื” ื›ืจื•ืš ื’ื ื‘ืขืœื•ื™ื•ืช ืžืฉืื‘ื™ื ื’ื“ื•ืœื•ืช ื™ื•ืชืจ.

ื”ืœื›ื ื• ื‘ืื•ืชื” ื“ืจืš ื”ืจื›ื‘ืช ื›ืœ ื”ื’ืจืกืื•ืช ื”ื“ืจื•ืฉื•ืช ื‘ืชืžื•ื ื” ืื—ืช. ื”ืกื˜ื˜ื™ืงื” ื”ืงื•ืžืคื™ืœื˜ื™ืช ืฉืœ ื›ืœ ื’ืจืกืื•ืช ื”ืืชืจ ืžืžื•ืงืžืช ื‘ืงื•ื ื˜ื™ื™ื ืจ ืขื NGINX, ื•ื”ืชื ื•ืขื” ืœืคืจื™ืกื” ื”ืžืงื‘ื™ืœื” ืžื’ื™ืขื” ื“ืจืš NGINX Ingress. ืžื‘ื ื” ืคืฉื•ื˜ - ืืคืœื™ืงืฆื™ื” ื—ืกืจืช ืžืฆื‘ - ืžืืคืฉืจ ืœืš ืœืฉื ื•ืช ื‘ืงืœื•ืช ืืช ื”-Deployment (ื‘ื”ืชืื ืœืขื•ืžืก) ื‘ืืžืฆืขื•ืช Kubernetes ืขืฆืžื”.

ืœื™ืชืจ ื“ื™ื•ืง, ืื ื• ืื•ืกืคื™ื ืฉืชื™ ืชืžื•ื ื•ืช: ืื—ืช ืขื‘ื•ืจ ืžืขื’ืœ ื”ื™ื™ืฆื•ืจ, ื”ืฉื ื™ื™ื” ื”ื™ื ืชืžื•ื ื” ื ื•ืกืคืช ืขื‘ื•ืจ ืžืขื’ืœ ื”ืคื™ืชื•ื—. ื”ืชืžื•ื ื” ื”ื ื•ืกืคืช ืžืฉืžืฉืช (ืžื•ืฉืงืช) ืจืง ื‘ืžืขื’ืœ ื”-dev ื™ื—ื“ ืขื ื”ืจืืฉื™ืช ื•ืžื›ื™ืœื” ืืช ื’ืจืกืช ื”ืืชืจ ืžื”- review commit, ื•ื”ื ื™ืชื•ื‘ ื‘ื™ื ื™ื”ื ืžืชื‘ืฆืข ื‘ืืžืฆืขื•ืช ืžืฉืื‘ื™ Ingress.

werf vs git clone ื•ื—ืคืฆื™ื

ื›ืคื™ ืฉื›ื‘ืจ ืฆื™ื™ื ื•, ืขืœ ืžื ืช ืœื™ืฆื•ืจ ืกื˜ื˜ื™ืงืช ืืชืจ ืขื‘ื•ืจ ื’ืจืกื” ืกืคืฆื™ืคื™ืช ืฉืœ ื”ืชื™ืขื•ื“, ืขืœื™ืš ืœื‘ื ื•ืช ืขืœ ื™ื“ื™ ืžืขื‘ืจ ืœืชื’ ื”ืžืื’ืจ ื”ืžืชืื™ื. ืืชื” ื™ื›ื•ืœ ื’ื ืœืขืฉื•ืช ื–ืืช ืขืœ ื™ื“ื™ ืฉื™ื‘ื•ื˜ ื”ืžืื’ืจ ื‘ื›ืœ ืคืขื ืฉืืชื” ื‘ื•ื ื”, ื‘ื—ื™ืจืช ื”ืชื’ื™ื ื”ืžืชืื™ืžื™ื ืžืจืฉื™ืžื”. ืขื ื–ืืช, ืžื“ื•ื‘ืจ ื‘ืคืขื•ืœื” ืขืชื™ืจืช ืžืฉืื‘ื™ื ื•ื™ืชืจื” ืžื›ืš, ืžืฆืจื™ื›ื” ื›ืชื™ื‘ืช ื”ื•ืจืื•ืช ืœื ื˜ืจื™ื•ื•ื™ืืœื™ื•ืช... ื—ื™ืกืจื•ืŸ ืจืฆื™ื ื™ ื ื•ืกืฃ ื”ื•ื ืฉื‘ื’ื™ืฉื” ื–ื• ืื™ืŸ ื“ืจืš ืœืื—ืกืŸ ืžืฉื”ื• ื‘ืžื˜ืžื•ืŸ ื‘ืžื”ืœืš ื”ื”ืจื›ื‘ื”.

ื›ืืŸ, ื›ืœื™ ื”ืฉื™ืจื•ืช werf ืขืฆืžื• ื‘ื ืœืขื–ืจืชื ื•, ืžื™ื™ืฉื ืžื˜ืžื•ืŸ ื—ื›ื ื•ืžืืคืฉืจ ืœืš ืœื”ืฉืชืžืฉ ืžืื’ืจื™ื ื—ื™ืฆื•ื ื™ื™ื. ืฉื™ืžื•ืฉ ื‘-werf ื›ื“ื™ ืœื”ื•ืกื™ืฃ ืงื•ื“ ืžื”ืžืื’ืจ ื™ืื™ืฅ ืžืฉืžืขื•ืชื™ืช ืืช ื”ื‘ื ื™ื™ื”, ืžื›ื™ื•ื•ืŸ werf ื‘ืขืฆื ืžืฉื‘ื˜ ืืช ื”ืžืื’ืจ ืคืขื ืื—ืช ื•ืื– ืžื‘ืฆืข ืจืง fetch ืื ื ื—ื•ืฅ. ื‘ื ื•ืกืฃ, ื‘ืขืช ื”ื•ืกืคืช ื ืชื•ื ื™ื ืžื”ืžืื’ืจ, ื ื•ื›ืœ ืœื‘ื—ื•ืจ ืจืง ืืช ื”ืกืคืจื™ื•ืช ื”ื“ืจื•ืฉื•ืช (ื‘ืžืงืจื” ืฉืœื ื• ื–ื• ื”ืกืคืจื™ื™ื” docs), ืžื” ืฉื™ืคื—ื™ืช ืžืฉืžืขื•ืชื™ืช ืืช ื›ืžื•ืช ื”ื ืชื•ื ื™ื ื”ื ื•ืกืคื™ื.

ืžื›ื™ื•ื•ืŸ ืฉ-Jekyll ื”ื•ื ื›ืœื™ ื”ืžื™ื•ืขื“ ืœืื™ืกื•ืฃ ื ืชื•ื ื™ื ืกื˜ื˜ื™ื™ื ื•ืื™ื ื• ื ื—ื•ืฅ ื‘ืชืžื•ื ื” ื”ืกื•ืคื™ืช, ื–ื” ื™ื”ื™ื” ื”ื’ื™ื•ื ื™ ืœืงืžืคืœ ื‘ ื—ืคืฅ werf, ื•ืœืชืžื•ื ื” ื”ืกื•ืคื™ืช ืœื™ื™ื‘ื ืจืง ืืช ืชื•ืฆืืช ื”ืงื•ืžืคื™ืœืฆื™ื”.

ืื ื—ื ื• ื›ื•ืชื‘ื™ื werf.yaml

ืื–, ื”ื—ืœื˜ื ื• ืฉื ืจื›ื™ื‘ ื›ืœ ื’ืจืกื” ื‘ื—ืคืฅ ื•ื•ืจืค ื ืคืจื“. ืœืžืจื•ืช ื–ืืช, ืื ื• ืื ื—ื ื• ืœื ื™ื•ื“ืขื™ื ื›ืžื” ืžื”ื—ืคืฆื™ื ื”ืืœื” ื™ื”ื™ื• ื‘ืžื”ืœืš ื”ื”ืจื›ื‘ื”, ืื– ืื ื—ื ื• ืœื ื™ื›ื•ืœื™ื ืœื›ืชื•ื‘ ืชืฆื•ืจืช ื‘ื ื™ื™ื” ืงื‘ื•ืขื” (ื‘ืื•ืคืŸ ืงืคื“ื ื™, ืื ื—ื ื• ืขื“ื™ื™ืŸ ื™ื›ื•ืœื™ื, ืื‘ืœ ื–ื” ืœื ื™ื”ื™ื” ื™ืขื™ืœ ืœื—ืœื•ื˜ื™ืŸ).

werf ืžืืคืฉืจ ืœืš ืœื”ืฉืชืžืฉ ืœืš ืชื‘ื ื™ื•ืช ื‘ืงื•ื‘ืฅ ื”ืชืฆื•ืจื” ืฉืœืš (werf.yaml), ื•ื–ื” ืžืืคืฉืจ ืืช ื–ื” ืœื™ืฆื•ืจ ืชืฆื•ืจื” ืชื•ืš ื›ื“ื™ ืชื ื•ืขื” ืชืœื•ื™ ื‘ื ืชื•ื ื™ื ื—ื™ืฆื•ื ื™ื™ื (ืžื” ืฉืืชื” ืฆืจื™ืš!). ื”ื ืชื•ื ื™ื ื”ื—ื™ืฆื•ื ื™ื™ื ื‘ืžืงืจื” ืฉืœื ื• ื”ื ืžื™ื“ืข ืขืœ ื’ืจืกืื•ืช ื•ืžื”ื“ื•ืจื•ืช, ืฉืขืœ ื‘ืกื™ืกืŸ ืื ื• ืื•ืกืคื™ื ืืช ื”ืžืกืคืจ ื”ื ื“ืจืฉ ืฉืœ ื—ืคืฆื™ื ื•ื›ืชื•ืฆืื” ืžื›ืš ืื ื• ืžืงื‘ืœื™ื ืฉืชื™ ืชืžื•ื ื•ืช: werf-doc ะธ werf-dev ืœืจื•ืฅ ืขืœ ืžืขื’ืœื™ื ืฉื•ื ื™ื.

ื ืชื•ื ื™ื ื—ื™ืฆื•ื ื™ื™ื ืžื•ืขื‘ืจื™ื ื“ืจืš ืžืฉืชื ื™ ืกื‘ื™ื‘ื”. ื”ื ื” ื”ื”ืจื›ื‘ ืฉืœื”ื:

  • RELEASES - ืฉื•ืจื” ืขื ืจืฉื™ืžืช ืžื”ื“ื•ืจื•ืช ื•ื”ื’ืจืกื” ื”ื ื•ื›ื—ื™ืช ื”ืžืชืื™ืžื” ืฉืœ werf, ื‘ืฆื•ืจื” ืฉืœ ืจืฉื™ืžืช ืขืจื›ื™ื ืžื•ืคืจื“ืช ื‘ืจื•ื•ื—ื™ื ื‘ืคื•ืจืžื˜ <ะะžะœะ•ะ _ะ ะ•ะ›ะ˜ะ—ะ>%<ะะžะœะ•ะ _ะ’ะ•ะ ะกะ˜ะ˜>. ื“ื•ื’ืžื: 1.0%v1.0.4-beta.20
  • CHANNELS - ืฉื•ืจื” ืขื ืจืฉื™ืžืช ืขืจื•ืฆื™ื ื•ื”ื’ืจืกื” ื”ื ื•ื›ื—ื™ืช ื”ืžืชืื™ืžื” ืฉืœ werf, ื‘ืฆื•ืจื” ืฉืœ ืจืฉื™ืžืช ืขืจื›ื™ื ืžื•ืคืจื“ืช ื‘ืจื•ื•ื—ื™ื ื‘ืคื•ืจืžื˜ <ะšะะะะ›>%<ะะžะœะ•ะ _ะ’ะ•ะ ะกะ˜ะ˜>. ื“ื•ื’ืžื: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION - ื’ืจืกืช ืฉื—ืจื•ืจ werf ืฉืชื•ืฆื’ ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื‘ืืชืจ (ืœื ืชืžื™ื“ ื™ืฉ ืฆื•ืจืš ืœื”ืฆื™ื’ ืชื™ืขื•ื“ ืœืคื™ ืžืกืคืจ ื”ื’ืจืกื” ื”ื’ื‘ื•ื” ื‘ื™ื•ืชืจ). ื“ื•ื’ืžื: v1.0.4-beta.20
  • REVIEW_SHA - hash ืฉืœ ืžื—ื•ื™ื‘ืช ื”ื‘ื™ืงื•ืจืช ืฉืžืžื ื” ืืชื” ืฆืจื™ืš ืœื‘ื ื•ืช ืืช ื”ื’ืจืกื” ืขื‘ื•ืจ ืœื•ืœืืช ื”ื‘ื“ื™ืงื”.

ืžืฉืชื ื™ื ืืœื• ื™ืžื•ืœืื• ื‘ืฆื™ื ื•ืจ GitLab CI, ื•ื›ื™ืฆื“ ื‘ื“ื™ื•ืง ื›ืชื•ื‘ ืœืžื˜ื”.

ืงื•ื“ื ื›ืœ, ืžื˜ืขืžื™ ื ื•ื—ื•ืช, ืื ื• ืžื’ื“ื™ืจื™ื ื‘ werf.yaml ืขื‘ื•ืจ ืœืžืฉืชื ื™ ืชื‘ื ื™ืช, ื”ืงืฆื” ืœื”ื ืขืจื›ื™ื ืžืžืฉืชื ื™ ืกื‘ื™ื‘ื”:

{{ $_ := set . "WerfVersions" (cat (env "CHANNELS") (env "RELEASES") | splitList " ") }}
{{ $Root := . }}
{{ $_ := set . "WerfRootVersion" (env "ROOT_VERSION") }}
{{ $_ := set . "WerfReviewCommit" (env "REVIEW_SHA") }}

ื”ืชื™ืื•ืจ ืฉืœ ื”ื—ืคืฅ ืœื”ื™ื“ื•ืจ ื”ื’ืจืกื” ื”ืกื˜ื˜ื™ืช ืฉืœ ื”ืืชืจ ื”ื•ื ื‘ื“ืจืš ื›ืœืœ ื–ื”ื” ืœื›ืœ ื”ืžืงืจื™ื ืฉืื ื• ืฆืจื™ื›ื™ื (ื›ื•ืœืœ ื™ืฆื™ืจืช ื’ืจืกืช ื”ืฉื•ืจืฉ, ื›ืžื• ื’ื ื”ื’ืจืกื” ืขื‘ื•ืจ ืžืขื’ืœ ื”-dev). ืœื›ืŸ, ื ืขื‘ื™ืจ ืื•ืชื• ืœื‘ืœื•ืง ื ืคืจื“ ื‘ืืžืฆืขื•ืช ื”ืคื•ื ืงืฆื™ื” define - ืœืฉื™ืžื•ืฉ ื—ื•ื–ืจ ืœืื—ืจ ืžื›ืŸ ืœืฉื™ืžื•ืฉ include. ื ืขื‘ื™ืจ ืืช ื”ื˜ื™ืขื•ื ื™ื ื”ื‘ืื™ื ืœืชื‘ื ื™ืช:

  • Version - ื’ืจืกื” ืฉื ื•ืฆืจื” (ืฉื ื”ืชื’);
  • Channel - ืฉื ืขืจื•ืฅ ื”ืขื“ื›ื•ืŸ ืฉืขื‘ื•ืจื• ื ื•ืฆืจ ื”ื—ืคืฅ;
  • Commit - commit hash, ืื ื”ื—ืคืฅ ื ื•ืฆืจ ืขื‘ื•ืจ ื”ืชื—ื™ื™ื‘ื•ืช ื‘ื™ืงื•ืจืช;
  • ื”ึถืงืฉืึตืจ.

ืชื™ืื•ืจ ืชื‘ื ื™ืช ื—ืคืฅ

{{- define "doc_artifact" -}}
{{- $Root := index . "Root" -}}
artifact: doc-{{ .Channel }}
from: jekyll/builder:3
mount:
- from: build_dir
  to: /usr/local/bundle
ansible:
  install:
  - shell: |
      export PATH=/usr/jekyll/bin/:$PATH
  - name: "Install Dependencies"
    shell: bundle install
    args:
      executable: /bin/bash
      chdir: /app/docs
  beforeSetup:
{{- if .Commit }}
  - shell: echo "Review SHA - {{ .Commit }}."
{{- end }}
{{- if eq .Channel "root" }}
  - name: "releases.yml HASH: {{ $Root.Files.Get "releases.yml" | sha256sum }}"
    copy:
      content: |
{{ $Root.Files.Get "releases.yml" | indent 8 }}
      dest:  /app/docs/_data/releases.yml
{{- else }}
  - file:
      path: /app/docs/_data/releases.yml
      state: touch
{{- end }}
  - file:
      path: "{{`{{ item }}`}}"
      state: directory
      mode: 0777
    with_items:
    - /app/main_site/
    - /app/ru_site/
  - file:
      dest: /app/docs/pages_ru/cli
      state: link
      src: /app/docs/pages/cli
  - shell: |
      echo -e "werfVersion: {{ .Version }}nwerfChannel: {{ .Channel }}" > /tmp/_config_additional.yml
      export PATH=/usr/jekyll/bin/:$PATH
{{- if and (ne .Version "review") (ne .Channel "root") }}
{{- $_ := set . "BaseURL" ( printf "v%s" .Channel ) }}
{{- else if ne .Channel "root" }}
{{- $_ := set . "BaseURL" .Channel }}
{{- end }}
      jekyll build -s /app/docs  -d /app/_main_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/tmp/_config_additional.yml
      jekyll build -s /app/docs  -d /app/_ru_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/app/docs/_config_ru.yml,/tmp/_config_additional.yml
    args:
      executable: /bin/bash
      chdir: /app/docs
git:
- url: https://github.com/flant/werf.git
  to: /app/
  owner: jekyll
  group: jekyll
{{- if .Commit }}
  commit: {{ .Commit }}
{{- else }}
  tag: {{ .Version }}
{{- end }}
  stageDependencies:
    install: ['docs/Gemfile','docs/Gemfile.lock']
    beforeSetup: '**/*'
  includePaths: 'docs'
  excludePaths: '**/*.sh'
{{- end }}

ืฉื ื”ื—ืคืฅ ื—ื™ื™ื‘ ืœื”ื™ื•ืช ื™ื™ื—ื•ื“ื™. ื ื•ื›ืœ ืœื”ืฉื™ื’ ื–ืืช, ืœืžืฉืœ, ืขืœ ื™ื“ื™ ื”ื•ืกืคืช ืฉื ื”ืขืจื•ืฅ (ืขืจืš ื”ืžืฉืชื ื” .Channel) ื›ืกื™ื•ืžืช ืœืฉื ืฉืœ ื”ื—ืคืฅ: artifact: doc-{{ .Channel }}. ืื‘ืœ ืืชื” ืฆืจื™ืš ืœื”ื‘ื™ืŸ ืฉื›ืืฉืจ ืžื™ื™ื‘ืื™ื ืžื—ืคืฆื™ื, ืชืฆื˜ืจืš ืœื”ืชื™ื™ื—ืก ืœืื•ืชื ืฉืžื•ืช.

ื‘ืขืช ืชื™ืื•ืจ ื—ืคืฅ, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ืชื›ื•ื ืช ื”-werf ื”ื‘ืื”: ื”ึทืจื›ึผึธื‘ึธื”. ื”ืจื›ื‘ื” ื”ืžืฆื™ื™ื ืช ืืช ืกืคืจื™ื™ืช ื”ืฉื™ืจื•ืช build_dir ืžืืคืฉืจ ืœืš ืœืฉืžื•ืจ ืืช ื”ืžื˜ืžื•ืŸ ืฉืœ Jekyll ื‘ื™ืŸ ืจื™ืฆื•ืช ืฆื™ื ื•ืจ, ืืฉืจ ืžืื™ืฅ ื‘ืื•ืคืŸ ืžืฉืžืขื•ืชื™ ืืช ื”ื”ืจื›ื‘ื” ืžื—ื“ืฉ.

ื™ื™ืชื›ืŸ ืฉื’ื ืฉืžืช ืœื‘ ืœืฉื™ืžื•ืฉ ื‘ืงื•ื‘ืฅ releases.yml ื”ื•ื ืงื•ื‘ืฅ YAML ืขื ื ืชื•ื ื™ ืฉื—ืจื•ืจ ืฉื”ืชื‘ืงืฉื• ืžืžื ื• github.com (ื—ืคืฅ ื”ืžืชืงื‘ืœ ื‘ืขืช ื‘ื™ืฆื•ืข ืฆื™ื ื•ืจ). ื–ื” ื ื—ื•ืฅ ื‘ืขืช ื”ื™ื“ื•ืจ ื”ืืชืจ, ืื‘ืœ ื‘ื”ืงืฉืจ ืฉืœ ื”ืžืืžืจ ื–ื” ืžืขื ื™ื™ืŸ ืื•ืชื ื• ื›ื™ ื–ื” ืชืœื•ื™ ื‘ืžืฆื‘ ืฉืœื• ื”ืจื›ื‘ื” ืžื—ื“ืฉ ืฉืœ ื—ืคืฅ ืื—ื“ ื‘ืœื‘ื“ - ื—ืคืฅ ืฉืœ ื’ืจืกืช ื”ื‘ืกื™ืก ืฉืœ ื”ืืชืจ (ืื™ืŸ ืฆื•ืจืš ื‘ื—ืคืฆื™ื ืื—ืจื™ื).

ื–ื” ืžื™ื•ืฉื ื‘ืืžืฆืขื•ืช ื”ื”ืฆื”ืจื” ื”ืžื•ืชื ื™ืช if ืœืš ืชื‘ื ื™ื•ืช ื•ืขื™ืฆื•ื‘ื™ื {{ $Root.Files.Get "releases.yml" | sha256sum }} ื‘ืฉืœื‘ ืฉืœื‘ื™ื. ื–ื” ืขื•ื‘ื“ ื‘ืื•ืคืŸ ื”ื‘ื: ื‘ืขืช ื‘ื ื™ื™ืช ื—ืคืฅ ืขื‘ื•ืจ ื’ืจืกืช ื”ืฉื•ืจืฉ (ืžืฉืชื ื” .Channel ืฉื•ื•ื” ืœ root) ืงื•ื‘ืฅ hash releases.yml ืžืฉืคื™ืข ืขืœ ื”ื—ืชื™ืžื” ืฉืœ ื›ืœ ื”ืฉืœื‘, ืžื›ื™ื•ื•ืŸ ืฉื”ื™ื ื—ืœืง ืžื”ืฉื ืฉืœ ื”ืžืฉื™ืžื” Ansible (ืคืจืžื˜ืจ name). ื›ืš, ื‘ืขืช ืฉื™ื ื•ื™ ืชื•ึนื›ึถืŸ ั„ะฐะนะปะฐ releases.yml ื”ื—ืคืฅ ื”ืžืชืื™ื ื™ื•ืจื›ื‘ ืžื—ื“ืฉ.

ืื ื ืฉื™ืžื• ืœื‘ ื’ื ืœืขื‘ื•ื“ื” ืขื ืžืื’ืจ ื—ื™ืฆื•ื ื™. ื‘ืชืžื•ื ื” ืฉืœ ื—ืคืฅ ืž ืžืื’ืจ werf, ืจืง ื”ืกืคืจื™ื™ื” ืžืชื•ื•ืกืคืช /docs, ื•ื‘ื”ืชืื ืœืคืจืžื˜ืจื™ื ืฉืขื‘ืจื•, ื”ื ืชื•ื ื™ื ืฉืœ ื”ืชื’ ืื• ื”ื‘ื™ืงื•ืจืช ื”ื ื“ืจืฉื™ื ืžืชื•ื•ืกืคื™ื ืžื™ื“.

ื›ื“ื™ ืœื”ืฉืชืžืฉ ื‘ืชื‘ื ื™ืช ื”ื—ืคืฅ ื›ื“ื™ ืœื™ืฆื•ืจ ืชื™ืื•ืจ ืฉืœ ื”ื—ืคืฅ ืฉืœ ื”ื’ืจืกืื•ืช ื”ืžื•ืขื‘ืจื•ืช ืฉืœ ืขืจื•ืฆื™ื ื•ืžื”ื“ื•ืจื•ืช, ืื ื• ืžืืจื’ื ื™ื ืœื•ืœืื” ืขืœ ื”ืžืฉืชื ื” .WerfVersions ะฒ werf.yaml:

{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ dict "Version" $VersionsDict._1 "Channel" $VersionsDict._0 "Root" $Root | include "doc_artifact" }}
---
{{ end -}}

ื›ื™ ื”ืœื•ืœืื” ืชื™ืฆื•ืจ ืžืกืคืจ ื—ืคืฆื™ื (ืื ื• ืžืงื•ื•ื™ื ืฉื›ืŸ), ื™ืฉ ืฆื•ืจืš ืœืงื—ืช ื‘ื—ืฉื‘ื•ืŸ ืืช ื”ืžืคืจื™ื“ ื‘ื™ื ื™ื”ื - ื”ืจืฆืฃ --- (ืœืžื™ื“ืข ื ื•ืกืฃ ืขืœ ืชื—ื‘ื™ืจ ืงื‘ืฆื™ ืชืฆื•ืจื”, ืจืื” ืชื™ืขื•ื“). ื›ืคื™ ืฉื”ื•ื’ื“ืจ ืงื•ื“ื ืœื›ืŸ, ื›ืืฉืจ ืงื•ืจืื™ื ืœืชื‘ื ื™ืช ื‘ืœื•ืœืื”, ืื ื• ืžืขื‘ื™ืจื™ื ืืช ืคืจืžื˜ืจื™ ื”ื’ืจืกื”, ื›ืชื•ื‘ืช ื”ืืชืจ ื•ื”ืงืฉืจ ื”ืฉื•ืจืฉ.

ื‘ืื•ืคืŸ ื“ื•ืžื”, ืืš ืœืœื ืœื•ืœืื”, ืื ื• ืงื•ืจืื™ื ืœืชื‘ื ื™ืช ื”ื—ืคืฆื™ื ืขื‘ื•ืจ "ืžืงืจื™ื ืžื™ื•ื—ื“ื™ื": ืขื‘ื•ืจ ื’ืจืกืช ื”ื‘ืกื™ืก, ื›ืžื• ื’ื ื”ื’ืจืกื” ืž-review commit:

{{ dict "Version" .WerfRootVersion "Channel" "root" "Root" $Root  | include "doc_artifact" }}
---
{{- if .WerfReviewCommit }}
{{ dict "Version" "review" "Channel" "review" "Commit" .WerfReviewCommit "Root" $Root  | include "doc_artifact" }}
{{- end }}

ืฉื™ื ืœื‘ ืฉื”ื—ืคืฅ ืขื‘ื•ืจ ืžื—ื•ื™ื‘ื•ืช ื”ื‘ื™ืงื•ืจืช ื™ื™ื‘ื ื” ืจืง ืื ื”ืžืฉืชื ื” ืžื•ื’ื“ืจ .WerfReviewCommit.

ื”ื—ืคืฆื™ื ืžื•ื›ื ื™ื - ื–ื” ื”ื–ืžืŸ ืœื”ืชื—ื™ืœ ืœื™ื™ื‘ื!

ื”ืชืžื•ื ื” ื”ืกื•ืคื™ืช, ืฉื ื•ืขื“ื” ืœืจื•ืฅ ืขืœ Kubernetes, ื”ื™ื NGINX ืจื’ื™ืœ ืขื ืงื•ื‘ืฅ ืชืฆื•ืจืช ืฉืจืช ื ื•ืกืฃ nginx.conf ื•ืกื˜ื˜ื™ ืžื—ืคืฆื™ื. ื‘ื ื•ืกืฃ ืœืืจื˜ื™ืคืงื˜ ืฉืœ ื’ืจืกืช ื”ืฉื•ืจืฉ ืฉืœ ื”ืืชืจ, ืขืœื™ื ื• ืœื—ื–ื•ืจ ืขืœ ื”ืœื•ืœืื” ืขืœ ื”ืžืฉืชื ื” .WerfVersions ื›ื“ื™ ืœื™ื™ื‘ื ื—ืคืฆื™ื ืฉืœ ื’ืจืกืื•ืช ืขืจื•ืฅ ื•ืฉื—ืจื•ืจ + ืคืขืœ ืœืคื™ ื›ืœืœ ืžืชืŸ ื”ืฉื ืฉืœ ื—ืคืฆื™ื ืฉืื™ืžืฆื ื• ืงื•ื“ื ืœื›ืŸ. ืžื›ื™ื•ื•ืŸ ืฉื›ืœ ื—ืคืฅ ืžืื—ืกืŸ ื’ืจืกืื•ืช ืฉืœ ื”ืืชืจ ืœืฉืชื™ ืฉืคื•ืช, ืื ื• ืžื™ื™ื‘ืื™ื ืื•ืชืŸ ืœืžืงื•ืžื•ืช ื”ืžืกื•ืคืงื™ื ืขืœ ื™ื“ื™ ื”ืชืฆื•ืจื”.

ืชื™ืื•ืจ ื”ืชืžื•ื ื” ื”ืกื•ืคื™ืช werf-doc

image: werf-doc
from: nginx:stable-alpine
ansible:
  setup:
  - name: "Setup /etc/nginx/nginx.conf"
    copy:
      content: |
{{ .Files.Get ".werf/nginx.conf" | indent 8 }}
      dest: /etc/nginx/nginx.conf
  - file:
      path: "{{`{{ item }}`}}"
      state: directory
      mode: 0777
    with_items:
    - /app/main_site/assets
    - /app/ru_site/assets
import:
- artifact: doc-root
  add: /app/_main_site
  to: /app/main_site
  before: setup
- artifact: doc-root
  add: /app/_ru_site
  to: /app/ru_site
  before: setup
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artifact: doc-{{ $Channel }}
  add: /app/_main_site
  to: /app/main_site/v{{ $Channel }}
  before: setup
{{ end -}}
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artifact: doc-{{ $Channel }}
  add: /app/_ru_site
  to: /app/ru_site/v{{ $Channel }}
  before: setup
{{ end -}}

ื”ืชืžื•ื ื” ื”ื ื•ืกืคืช, ืฉื™ื—ื“ ืขื ื”ืจืืฉื™ืช, ืžื•ืฉืงืช ื‘ืžืขื’ืœ ื”-dev, ืžื›ื™ืœื” ืจืง ืฉืชื™ ื’ืจืกืื•ืช ืฉืœ ื”ืืชืจ: ื”ื’ืจืกื” ืžื”- review commit ื•ื’ืจืกืช ื”ื‘ืกื™ืก ืฉืœ ื”ืืชืจ (ื™ืฉื ื ื ื›ืกื™ื ื›ืœืœื™ื™ื ื•ืื ืืชื” ื–ื•ื›ืจ , ืฉื—ืจืจ ื ืชื•ื ื™ื). ืœืคื™ื›ืš, ื”ืชืžื•ื ื” ื”ื ื•ืกืคืช ืชื”ื™ื” ืฉื•ื ื” ืžื”ืจืืฉื™ืช ืจืง ื‘ืงื˜ืข ื”ื™ื™ื‘ื•ื โ€‹โ€‹(ื•ื›ืžื•ื‘ืŸ ื‘ืฉื):

image: werf-dev
...
import:
- artifact: doc-root
  add: /app/_main_site
  to: /app/main_site
  before: setup
- artifact: doc-root
  add: /app/_ru_site
  to: /app/ru_site
  before: setup
{{- if .WerfReviewCommit  }}
- artifact: doc-review
  add: /app/_main_site
  to: /app/main_site/review
  before: setup
- artifact: doc-review
  add: /app/_ru_site
  to: /app/ru_site/review
  before: setup
{{- end }}

ื›ืคื™ ืฉืฆื•ื™ืŸ ืœืขื™ืœ, ื”ื—ืคืฅ ืขื‘ื•ืจ ืžื—ื•ื™ื‘ื•ืช ื”ื‘ื™ืงื•ืจืช ื™ื™ื•ื•ืฆืจ ืจืง ื›ืืฉืจ ืžืฉืชื ื” ื”ืกื‘ื™ื‘ื” ืฉื ืงื‘ืข ืžื•ืคืขืœ REVIEW_SHA. ื–ื” ื™ื”ื™ื” ืืคืฉืจื™ ื‘ื›ืœืœ ืœื ืœื™ืฆื•ืจ ืืช ืชืžื•ื ืช werf-dev ืื ืื™ืŸ ืžืฉืชื ื” ืกื‘ื™ื‘ื” REVIEW_SHA, ืื‘ืœ ื›ื“ื™ ื ื™ืงื™ื•ืŸ ืœืคื™ ืคื•ืœื™ืกื•ืช ืชืžื•ื ื•ืช Docker ื‘-werf ืขื‘ื“ื• ืขื‘ื•ืจ ืชืžื•ื ืช werf-dev, ื ืฉืื™ืจ ืื•ืชื” ืœื‘ื ื•ืช ืจืง ืขื ื—ืคืฅ ื’ืจืกืช ื”ืฉื•ืจืฉ (ื”ื•ื ื›ื‘ืจ ื‘ื ื•ื™ ื‘ื›ืœ ืžืงืจื”), ื›ื“ื™ ืœืคืฉื˜ ืืช ืžื‘ื ื” ื”ืฆื™ื ื•ืจ.

ื”ื”ืจื›ื‘ื” ืžื•ื›ื ื”! ื‘ื•ืื• ื ืขื‘ื•ืจ ืœ-CI/CD ื•ืœื ื™ื•ืื ืกื™ื ื—ืฉื•ื‘ื™ื.

ืฆื™ื ื•ืจ ื‘- GitLab CI ื•ืชื›ื•ื ื•ืช ืฉืœ ื‘ื ื™ื™ื” ื“ื™ื ืžื™ืช

ื‘ืขืช ื”ืคืขืœืช ื”-build ืขืœื™ื ื• ืœื”ื’ื“ื™ืจ ืืช ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ื‘ื”ื ื ืขืฉื” ืฉื™ืžื•ืฉ werf.yaml. ื–ื” ืœื ื—ืœ ืขืœ ื”ืžืฉืชื ื” REVIEW_SHA, ืื•ืชื• ื ื’ื“ื™ืจ ื‘ืขืช ืงืจื™ืืช pipeline ืžื”-GitHub hook.

ืื ื• ื ื™ืฆื•ืจ ืืช ื”ื ืชื•ื ื™ื ื”ื—ื™ืฆื•ื ื™ื™ื ื”ื“ืจื•ืฉื™ื ื‘ืกืงืจื™ืคื˜ ืฉืœ Bash generate_artifacts, ืฉื™ื™ืฆื•ืจ ืฉื ื™ ื—ืคืฆื™ ืฆื™ื ื•ืจ ืฉืœ GitLab:

  • ั„ะฐะนะป releases.yml ืขื ื ืชื•ื ื™ ืฉื—ืจื•ืจ,
  • ั„ะฐะนะป common_envs.sh, ื”ืžื›ื™ืœ ืืช ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ื”ืžื™ื•ืขื“ื™ื ืœื™ื™ืฆื•ื.

ืชื•ื›ืŸ ื”ืงื•ื‘ืฅ generate_artifacts ืชืžืฆื ืืฆืœื ื• ืžืื’ืจื™ื ืขื ื“ื•ื’ืžืื•ืช. ืจื›ื™ืฉืช ื”ื ืชื•ื ื™ื ืขืฆืžื” ืื™ื ื” ื ื•ืฉื ื”ืžืืžืจ, ืืœื ื”ืงื•ื‘ืฅ common_envs.sh ื—ืฉื•ื‘ ืœื ื•, ื›ื™ ื”ืขื‘ื•ื“ื” ืฉืœ werf ืชืœื•ื™ื” ื‘ื–ื”. ื“ื•ื’ืžื” ืœืชื•ื›ืŸ ืฉืœื•:

export RELEASES='1.0%v1.0.6-4'
export CHANNELS='1.0-alpha%v1.0.7-1 1.0-beta%v1.0.7-1 1.0-ea%v1.0.6-4 1.0-stable%v1.0.6-4 1.0-rock-solid%v1.0.6-4'
export ROOT_VERSION='v1.0.6-4'

ืืชื” ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ ื‘ืคืœื˜ ืฉืœ ืกืงืจื™ืคื˜ ื›ื–ื”, ืœืžืฉืœ, ื‘ืืžืฆืขื•ืช ื”ืคื•ื ืงืฆื™ื” Bash source.

ืขื›ืฉื™ื• ืžื’ื™ืข ื”ื—ืœืง ื”ื›ื™ืคื™. ืขืœ ืžื ืช ืฉื’ื ื”ื‘ื ื™ื™ื” ื•ื’ื ื”ืคืจื™ืกื” ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ื™ืคืขืœื• ื›ื”ืœื›ื”, ื™ืฉ ืฆื•ืจืš ืœื”ื‘ื˜ื™ื— ื–ืืช werf.yaml ื”ื™ื” ืื•ืชื• ื”ื“ื‘ืจ ืœืคื—ื•ืช ื‘ืชื•ืš ืฆื™ื ื•ืจ ืื—ื“. ืื ืชื ืื™ ื–ื” ืœื ืžืชืงื™ื™ื, ืื–ื™ ื”ื—ืชื™ืžื•ืช ืฉืœ ื”ืฉืœื‘ื™ื ืฉ-werf ืžื—ืฉื‘ ื‘ืžื”ืœืš ื”ื”ืจื›ื‘ื”, ืœืžืฉืœ, ื”ืคืจื™ืกื”, ื™ื”ื™ื• ืฉื•ื ื•ืช. ื–ื” ื™ื•ื‘ื™ืœ ืœืฉื’ื™ืืช ืคืจื™ืกื”, ื›ื™... ื”ืชืžื•ื ื” ื”ื ื“ืจืฉืช ืœืคืจื™ืกื” ืชื—ืกืจ.

ื‘ืžื™ืœื™ื ืื—ืจื•ืช, ืื ื‘ืžื”ืœืš ื”ื”ืจื›ื‘ื” ืฉืœ ืชืžื•ื ืช ื”ืืชืจ ื”ืžื™ื“ืข ืขืœ ืžื”ื“ื•ืจื•ืช ื•ื’ืจืกืื•ืช ื–ื”ื”, ื•ื‘ื–ืžืŸ ื”ืคืจื™ืกื” ื™ื•ืฆืืช ื’ืจืกื” ื—ื“ืฉื” ื•ืœืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื” ื™ืฉ ืขืจื›ื™ื ืฉื•ื ื™ื, ื”ืจื™ ืฉื”ืคืจื™ืกื” ืชื™ื›ืฉืœ ืขื ืฉื’ื™ืื”: ืื—ืจื™ ื”ื›ืœ, ื”ื—ืคืฅ ืฉืœ ื”ื’ืจืกื” ื”ื—ื“ืฉื” ืขื“ื™ื™ืŸ ืœื ื ื‘ื ื”.

ืื ื“ื•ืจ werf.yaml ืชืœื•ื™ ื‘ื ืชื•ื ื™ื ื—ื™ืฆื•ื ื™ื™ื (ืœื“ื•ื’ืžื”, ืจืฉื™ืžื” ืฉืœ ื’ืจืกืื•ืช ื ื•ื›ื—ื™ื•ืช, ื›ืžื• ื‘ืžืงืจื” ืฉืœื ื•), ืื– ื™ืฉ ืœืจืฉื•ื ืืช ื”ื”ืจื›ื‘ ื•ื”ืขืจื›ื™ื ืฉืœ ื ืชื•ื ื™ื ื›ืืœื” ื‘ืชื•ืš ื”ืฆื™ื ื•ืจ. ื–ื” ื—ืฉื•ื‘ ื‘ืžื™ื•ื—ื“ ืื ืคืจืžื˜ืจื™ื ื—ื™ืฆื•ื ื™ื™ื ืžืฉืชื ื™ื ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืœืžื“ื™.

ืื ื• ืœืงื‘ืœ ื•ืœื”ืงืœื™ื˜ ื ืชื•ื ื™ื ื—ื™ืฆื•ื ื™ื™ื ื‘ืฉืœื‘ ื”ืจืืฉื•ืŸ ืฉืœ ื”ืฆื™ื ื•ืจ ื‘-GitLab (ื‘ื ื™ื™ื” ืžืจืืฉ) ื•ืฉื“ืจ ืื•ืชื ื”ืœืื” ื‘ื˜ื•ืคืก ื—ืคืฅ GitLab CI. ื–ื” ื™ืืคืฉืจ ืœืš ืœื”ืคืขื™ืœ ื•ืœื”ืคืขื™ืœ ืžื—ื“ืฉ ืขื‘ื•ื“ื•ืช ืฆื™ื ื•ืจ (ื‘ื ื™ื™ื”, ืคืจื™ืกื”, ื ื™ืงื•ื™) ืขื ืื•ืชื” ืชืฆื•ืจื” ื‘ werf.yaml.

ืชื•ื›ืŸ ื”ื‘ืžื” ื‘ื ื™ื™ื” ืžืจืืฉ ั„ะฐะนะปะฐ .gitlab-ci.yml:

Prebuild:
  stage: prebuild
  script:
    - bash ./generate_artifacts 1> common_envs.sh
    - cat ./common_envs.sh
  artifacts:
    paths:
      - releases.yml
      - common_envs.sh
    expire_in: 2 week

ืœืื—ืจ ืœื›ื™ื“ืช ื”ื ืชื•ื ื™ื ื”ื—ื™ืฆื•ื ื™ื™ื ื‘-Artifact, ืืชื” ื™ื›ื•ืœ ืœื‘ื ื•ืช ื•ืœืคืจื•ืก ื‘ืืžืฆืขื•ืช ืฉืœื‘ื™ ื”ืฆื™ื ื•ืจ ื”ืกื˜ื ื“ืจื˜ื™ื™ื ืฉืœ GitLab CI: Build and Deploy. ืื ื• ืžืฉื™ืงื™ื ืืช ื”ืฆื™ื ื•ืจ ืขืฆืžื• ื‘ืืžืฆืขื•ืช ื”ื•ืงืก ืžืžืื’ืจ GitHub werf (ื›ืœื•ืžืจ, ื›ืืฉืจ ื™ืฉ ืฉื™ื ื•ื™ื™ื ื‘ืžืื’ืจ ื‘- GitHub). ื ื™ืชืŸ ืœืžืฆื•ื ื ืชื•ื ื™ื ืขื‘ื•ืจื ื‘ืžืืคื™ื™ื ื™ ื”ืคืจื•ื™ืงื˜ ืฉืœ GitLab ื‘ืžื“ื•ืจ ื”ื’ื“ืจื•ืช CI/CD -> ืžืคืขื™ืœื™ ืฆื™ื ื•ืจ, ื•ืœืื—ืจ ืžื›ืŸ ืฆื•ืจ ืืช ื”-Webhook ื”ืžืชืื™ื ื‘-GitHub (ื”ื’ื“ืจื•ืช -> Webhooks).

ืฉืœื‘ ื”ื‘ื ื™ื™ื” ื™ื™ืจืื” ื›ืš:

Build:
  stage: build
  script:
    - type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
    - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
    - source common_envs.sh
    - werf build-and-publish --stages-storage :local
  except:
    refs:
      - schedules
  dependencies:
    - Prebuild

GitLab ื™ื•ืกื™ืฃ ืฉื ื™ ื—ืคืฆื™ื ืžื”ืฉืœื‘ ืœืฉืœื‘ ื”ื‘ื ื™ื™ื” ื‘ื ื™ื™ื” ืžืจืืฉ, ืื– ืื ื• ืžื™ื™ืฆืื™ื ืžืฉืชื ื™ื ืขื ื ืชื•ื ื™ ืงืœื˜ ืžื•ื›ื ื™ื ื‘ืืžืฆืขื•ืช ื”ืžื‘ื ื” source common_envs.sh. ืื ื• ืžืชื—ื™ืœื™ื ืืช ืฉืœื‘ ื”ื‘ื ื™ื™ื” ื‘ื›ืœ ื”ืžืงืจื™ื, ืœืžืขื˜ ื”ืฉืงืช ื”ืฆื™ื ื•ืจ ืœืคื™ ืœื•ื— ื–ืžื ื™ื. ืขืœ ืคื™ ืœื•ื— ื”ื–ืžื ื™ื ื ืคืขื™ืœ ืฆื ืจืช ืœื ื™ืงื™ื•ืŸ - ื‘ืžืงืจื” ื–ื” ืื™ืŸ ืฆื•ืจืš ื‘ื‘ื™ืฆื•ืข ื”ืจื›ื‘ื”.

ื‘ืฉืœื‘ ื”ืคืจื™ืกื”, ื ืชืืจ ืฉืชื™ ืžืฉื™ืžื•ืช - ื‘ื ืคืจื“ ืœืคืจื™ืกื” ืœืžืขื’ืœื™ ื™ื™ืฆื•ืจ ื•ืคื™ืชื•ื—, ื‘ืืžืฆืขื•ืช ืชื‘ื ื™ืช YAML:

.base_deploy: &base_deploy
  stage: deploy
  script:
    - type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
    - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
    - source common_envs.sh
    - werf deploy --stages-storage :local
  dependencies:
    - Prebuild
  except:
    refs:
      - schedules

Deploy to Production:
  <<: *base_deploy
  variables:
    WERF_KUBE_CONTEXT: prod
  environment:
    name: production
    url: werf.io
  only:
    refs:
      - master
  except:
    variables:
      - $REVIEW_SHA
    refs:
      - schedules

Deploy to Test:
  <<: *base_deploy
  variables:
    WERF_KUBE_CONTEXT: dev
  environment:
    name: test
    url: werf.test.flant.com
  except:
    refs:
      - schedules
  only:
    variables:
      - $REVIEW_SHA

ื”ืžืฉื™ืžื•ืช ืฉื•ื ื•ืช ื‘ืžื”ื•ืช ืจืง ื‘ืฆื™ื•ืŸ ื”ื”ืงืฉืจ ืฉืœ ื”ืืฉื›ื•ืœ ืฉืืœื™ื• werf ืฆืจื™ื›ื” ืœื‘ืฆืข ืืช ื”ืคืจื™ืกื” (WERF_KUBE_CONTEXT), ื•ื”ื’ื“ืจืช ืžืฉืชื ื™ ืกื‘ื™ื‘ืช ื”ืœื•ืœืื” (environment.name ะธ environment.url), ืืฉืจ ืžืฉืžืฉื™ื ืœืื—ืจ ืžื›ืŸ ื‘ืชื‘ื ื™ื•ืช ืชืจืฉื™ื Helm. ืœื ื ืกืคืง ืืช ืชื•ื›ืŸ ื”ืชื‘ื ื™ื•ืช, ื›ื™... ืื™ืŸ ืฉื ืฉื•ื ื“ื‘ืจ ืžืขื ื™ื™ืŸ ืœื ื•ืฉื ื”ืžื“ื•ื‘ืจ, ืื‘ืœ ืืชื” ื™ื›ื•ืœ ืœืžืฆื•ื ืื•ืชื ื‘ ืžืื’ืจื™ื ืขื‘ื•ืจ ื”ืžืืžืจ.

ื”ืžื’ืข ื”ืกื•ืคื™

ืžื›ื™ื•ื•ืŸ ืฉื’ืจืกืื•ืช werf ืžืฉื•ื—ืจืจื•ืช ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืœืžื“ื™, ืชืžื•ื ื•ืช ื—ื“ืฉื•ืช ื™ื™ื‘ื ื• ืœืขืชื™ื ืงืจื•ื‘ื•ืช, ื•ื”-Docker Registry ื™ื’ื“ืœ ื›ืœ ื”ื–ืžืŸ. ืœื›ืŸ, ื”ื›ืจื—ื™ ืœื”ื’ื“ื™ืจ ื ื™ืงื•ื™ ืชืžื•ื ื” ืื•ื˜ื•ืžื˜ื™ ืขืœ ืกืžืš ืžื“ื™ื ื™ื•ืช. ื–ื” ืžืื•ื“ ืงืœ ืœืขืฉื•ืช.

ื›ื“ื™ ืœื™ื™ืฉื ืชืฆื˜ืจืš:

  • ื”ื•ืกืฃ ืฉืœื‘ ื ื™ืงื•ื™ ืœ .gitlab-ci.yml;
  • ื”ื•ืกืฃ ื‘ื™ืฆื•ืข ืชืงื•ืคืชื™ ืฉืœ ืžืฉื™ืžืช ื ื™ืงื•ื™;
  • ื”ื’ื“ืจ ืžืฉืชื ื” ืกื‘ื™ื‘ื” ืขื ืืกื™ืžื•ืŸ ื’ื™ืฉื” ืœื›ืชื™ื‘ื”.

ื”ื•ืกืคืช ืฉืœื‘ ื ื™ืงื•ื™ ืœ .gitlab-ci.yml:

Cleanup:
  stage: cleanup
  script:
    - type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
    - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
    - source common_envs.sh
    - docker login -u nobody -p ${WERF_IMAGES_CLEANUP_PASSWORD} ${WERF_IMAGES_REPO}
    - werf cleanup --stages-storage :local
  only:
    refs:
      - schedules

ื›ื‘ืจ ืจืื™ื ื• ื›ืžืขื˜ ืืช ื›ืœ ื–ื” ืงืฆืช ื™ื•ืชืจ ื’ื‘ื•ื” - ืจืง ื›ื“ื™ ืœื ืงื•ืช ืืช ื–ื” ืฆืจื™ืš ืœื”ื™ื›ื ืก ืชื—ื™ืœื” ืœ-Docker Registry ืขื ืืกื™ืžื•ืŸ ืฉื™ืฉ ืœื• ืืช ื”ื–ื›ื•ื™ื•ืช ืœืžื—ื•ืง ืชืžื•ื ื•ืช ื‘-Docker Registry (ืืกื™ืžื•ืŸ ื”ืžืฉื™ืžื” ืฉืœ GitLab CI ืฉื”ื•ื ืคืง ืื•ื˜ื•ืžื˜ื™ืช ืœื ื™ืฉ ื–ื›ื•ื™ื•ืช ื›ืืœื”). ื™ืฉ ืœื™ืฆื•ืจ ืืช ื”ืืกื™ืžื•ืŸ ื‘-GitLab ืžืจืืฉ ื•ืœืฆื™ื™ืŸ ืืช ื”ืขืจืš ืฉืœื• ื‘ืžืฉืชื ื” ื”ืกื‘ื™ื‘ื” WERF_IMAGES_CLEANUP_PASSWORD ืคืจื•ื™ื™ืงื˜ (ื”ื’ื“ืจื•ืช CI/CD -> ืžืฉืชื ื™ื).

ื”ื•ืกืคืช ืžืฉื™ืžืช ื ื™ืงื™ื•ืŸ ืขื ืœื•ื— ื”ื–ืžื ื™ื ื”ื ื“ืจืฉ ืžืชื‘ืฆืขืช ื‘ CI/CD ->
ืœื•ื—ื•ืช ื–ืžื ื™ื
.

ื–ื”ื•: ืคืจื•ื™ืงื˜ ื‘-Docker Registry ื›ื‘ืจ ืœื ื™ืฆืžื— ื›ืœ ื”ื–ืžืŸ ืžืชืžื•ื ื•ืช ืฉืื™ื ืŸ ื‘ืฉื™ืžื•ืฉ.

ื‘ืกื•ืฃ ื”ื—ืœืง ื”ืžืขืฉื™, ื”ืจืฉื• ืœื™ ืœื”ื–ื›ื™ืจ ืœื›ื ืฉื”ืจื™ืฉื•ืžื™ื ื”ืžืœืื™ื ืžื”ืžืืžืจ ื–ืžื™ื ื™ื ื‘ Git:

ืชื•ืฆืื”

  1. ืงื™ื‘ืœื ื• ืžื‘ื ื” ื”ืจื›ื‘ื” ืœื•ื’ื™: ื—ืคืฅ ืื—ื“ ืœื›ืœ ื’ืจืกื”.
  2. ื”ื”ืจื›ื‘ื” ื”ื™ื ืื•ื ื™ื‘ืจืกืœื™ืช ื•ืื™ื ื” ื“ื•ืจืฉืช ืฉื™ื ื•ื™ื™ื ื™ื“ื ื™ื™ื ื›ืืฉืจ ื™ื•ืฆืื•ืช ื’ืจืกืื•ืช ื—ื“ืฉื•ืช ืฉืœ werf: ื”ืชื™ืขื•ื“ ื‘ืืชืจ ืžืชืขื“ื›ืŸ ืื•ื˜ื•ืžื˜ื™ืช.
  3. ืฉืชื™ ืชืžื•ื ื•ืช ืžื•ืจื›ื‘ื•ืช ืœืงื•ื•ื™ ืžืชืืจ ืฉื•ื ื™ื.
  4. ื–ื” ืขื•ื‘ื“ ืžื”ืจ, ื›ื™ ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘-Caching ื›ื›ืœ ื”ืืคืฉืจ - ื›ืืฉืจ ืžืฉื•ื—ืจืจืช ื’ืจืกื” ื—ื“ืฉื” ืฉืœ werf ืื• ื”ื•ืง ืฉืœ GitHub ื ืงืจื ืœื‘ื™ืฆื•ืข ื‘ื™ืงื•ืจืช, ืจืง ื”ื—ืคืฅ ื”ืžืชืื™ื ืขื ื”ื’ืจืกื” ืฉืฉื•ื ืชื” ื ื‘ื ื” ืžื—ื“ืฉ.
  5. ืื™ืŸ ืฆื•ืจืš ืœื—ืฉื•ื‘ ืขืœ ืžื—ื™ืงืช ืชืžื•ื ื•ืช ืฉืื™ื ืŸ ื‘ืฉื™ืžื•ืฉ: ื ื™ืงื•ื™ ืœืคื™ ืžื“ื™ื ื™ื•ืช werf ื™ืฉืžื•ืจ ืขืœ ื”ืกื“ืจ ืฉืœ ื”-Docker Registry.

ืžืžืฆืื™ื

  • ืฉื™ืžื•ืฉ ื‘-werf ืžืืคืฉืจ ืœืžื›ืœื•ืœ ืœืขื‘ื•ื“ ื‘ืžื”ื™ืจื•ืช ืขืงื‘ ืฉืžื™ืจื” ื‘ืžื˜ืžื•ืŸ ื”ืŸ ืฉืœ ื”ืžื›ืœื•ืœ ืขืฆืžื• ื•ื”ืŸ ืฉืœ ืžื˜ืžื•ืŸ ื‘ืขืช โ€‹โ€‹ืขื‘ื•ื“ื” ืขื ืžืื’ืจื™ื ื—ื™ืฆื•ื ื™ื™ื.
  • ืขื‘ื•ื“ื” ืขื ืžืื’ืจื™ Git ื—ื™ืฆื•ื ื™ื™ื ืžื‘ื˜ืœืช ืืช ื”ืฆื•ืจืš ืœืฉื›ืคืœ ืืช ื›ืœ ื”ืžืื’ืจ ื‘ื›ืœ ืคืขื ืื• ืœื”ืžืฆื™ื ืžื—ื“ืฉ ืืช ื”ื’ืœื’ืœ ืขื ื”ื™ื’ื™ื•ืŸ ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืžืกื•ื‘ืš. werf ืžืฉืชืžืฉ ื‘ืžื˜ืžื•ืŸ ื•ืขื•ืฉื” ืืช ื”ืฉื™ื‘ื•ื˜ ืคืขื ืื—ืช ื‘ืœื‘ื“, ื•ืœืื—ืจ ืžื›ืŸ ืžืฉืชืžืฉ fetch ื•ืจืง ื›ืฉืฆืจื™ืš.
  • ื™ื›ื•ืœืช ืœื”ืฉืชืžืฉ ื‘ืชื‘ื ื™ื•ืช Go ื‘ืงื•ื‘ืฅ ืชืฆื•ืจืช ื”-build werf.yaml ืžืืคืฉืจ ืœืš ืœืชืืจ ืžื›ืœื•ืœ ืฉืชื•ืฆืืชื” ืชืœื•ื™ื” ื‘ื ืชื•ื ื™ื ื—ื™ืฆื•ื ื™ื™ื.
  • ืฉื™ืžื•ืฉ ื‘-mount ื‘-werf ืžืื™ืฅ ื‘ืื•ืคืŸ ืžืฉืžืขื•ืชื™ ืืช ืื•ืกืฃ ื”ื—ืคืฆื™ื - ื‘ืฉืœ ื”ืžื˜ืžื•ืŸ, ื”ืžืฉื•ืชืฃ ืœื›ืœ ื”ืฆื™ื ื•ืจื•ืช.
  • werf ืžืงืœ ืขืœ ืชืฆื•ืจืช ื”ื ื™ืงื•ื™, ื•ื–ื” ื—ืฉื•ื‘ ื‘ืžื™ื•ื—ื“ ื‘ืขืช ื‘ื ื™ื™ื” ื“ื™ื ืžื™ืช.

ื .ื‘.

ืงืจื ื’ื ื‘ื‘ืœื•ื’ ืฉืœื ื•:

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”