{"id":469913,"date":"2025-08-07T09:00:44","date_gmt":"2025-08-07T09:00:44","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=469913"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=469913","title":{"rendered":"<span>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 Portainer \u0432 CI\/CD \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u0445<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 Portainer \u0438 \u0441\u0444\u0435\u0440\u0430\u043c\u0438 \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u0434\u0432\u0443\u0445 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445:<\/p>\n<ul>\n<li>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f: \u00ab<a href=\"https:\/\/habr.com\/ru\/articles\/917886\/\" rel=\"noopener noreferrer nofollow\">\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0434\u0435\u043f\u043b\u043e\u0439 \u0431\u043e\u0442\u0430 (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e) \u043d\u0430 Docker-\u0445\u043e\u0441\u0442\u0438\u043d\u0433\u0435 \u0441 Portainer<\/a>\u00bb<\/p>\n<\/li>\n<li>\n<p>\u0412\u0442\u043e\u0440\u0430\u044f: \u00ab<a href=\"https:\/\/habr.com\/ru\/articles\/924528\/\" rel=\"noopener noreferrer nofollow\">\u041e\u0434\u0438\u043d Portainer, \u0447\u0442\u043e\u0431 \u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435\u043c\u0438<\/a>\u00bb<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0434\u0435\u0441\u044c \u0432\u043f\u0435\u0440\u0432\u044b\u0435: <strong>Portainer<\/strong> \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u043f\u0430\u043d\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Docker (\u0438 Docker Swarm\/Kubernetes): \u0437\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441\u0435\u0442\u0438, \u0442\u043e\u043c\u0430 \u0438 \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u2014 \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.<\/p>\n<p>\u041c\u044b \u0443\u0436\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Portainer;<\/p>\n<\/li>\n<li>\n<p>\u0447\u0442\u043e \u0437\u0430 \u0441\u0435\u0440\u0432\u0438\u0441 <a href=\"http:\/\/DockerHosting.ru\" rel=\"noopener noreferrer nofollow\">DockerHosting.ru<\/a> \u0438 \u043a\u0430\u043a \u043e\u043d \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c <code>Dockerfile<\/code> \u0438 <code>docker-compose.yml<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u0437 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043a Portainer \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043d\u0438\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438 Docker.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c, <strong>\u043a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c Portainer \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b CI\/CD \u0438 \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c Docker-\u043e\u0431\u0440\u0430\u0437\u044b<\/strong>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0437\u043d\u0430\u0435\u043c, <strong>\u043a\u0430\u043a \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c Portainer Business Edition<\/strong>.<\/p>\n<blockquote>\n<p>\u041a\u043e\u0440\u043e\u0442\u043a\u043e \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u0441\u044f \u0441 \u0442\u0435\u043c\u043e\u0439:  <br \/>   <strong>CI<\/strong> (Continuous Integration) \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0434\u0430 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438.  <br \/>   <strong>CD<\/strong> (Continuous Delivery\/Deployment) \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0430\/\u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.  <br \/>   <strong>\u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 (registry)<\/strong> \u2014 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432 (\u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0435 \u0438\u043b\u0438 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0435), \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e Portainer \u0438 \u0432\u0430\u0448\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u043e\u0431\u0440\u0430\u0437\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f.<\/p>\n<\/blockquote>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043a \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u044e \u00ab<a href=\"https:\/\/pressanybutton.ru\/post\/devops\/cicd-osnovy-napisaniya-workflow\/\" rel=\"noopener noreferrer nofollow\">CI\/CD: \u043e\u0441\u043d\u043e\u0432\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f Workflow<\/a>\u00bb, \u0447\u0442\u043e\u0431\u044b \u0433\u043b\u0443\u0431\u0436\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u0438\u044f CI\/CD \u0438 Workflow.<\/p>\n<hr\/>\n<h3>\u0413\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c Docker-\u043e\u0431\u0440\u0430\u0437\u044b<\/h3>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449 (Docker Registry). <code>Dockerfile<\/code> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, <strong>\u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437<\/strong>, \u0430 \u0437\u0430\u043f\u0438\u0441\u044c <code>build: .<\/code> \u0432 <code>docker-compose.yml<\/code> \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0435\u0433\u043e <strong>\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e<\/strong>.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: <strong>\u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0435\u0441\u0442\u0440<\/strong>. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u0434\u0435\u043f\u043b\u043e\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 <code>docker pull<\/code> \u0438 \u0437\u0430\u0431\u0435\u0440\u0451\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f CI\/CD: \u0432\u0441\u044f \u0442\u044f\u0436\u0451\u043b\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0435, \u0430 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430.<\/p>\n<h4>\u041a\u0430\u043a\u0438\u0435 \u0431\u044b\u0432\u0430\u044e\u0442 \u0440\u0435\u0435\u0441\u0442\u0440\u044b<\/h4>\n<ul>\n<li>\n<p><strong>Docker Hub<\/strong> \u2014 \u0441\u0430\u043c\u043e\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>Self-hosted<\/strong> \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <strong>Harbor<\/strong> \u2014 \u0440\u0435\u0435\u0441\u0442\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0435 \u043d\u0430 \u0441\u0432\u043e\u0451\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u0435\u0441\u0442\u0440\u044b \u0443 git-\u0445\u043e\u0441\u0442\u0438\u043d\u0433\u043e\u0432<\/strong>: <strong>GitHub Container Registry (<\/strong><a href=\"http:\/\/ghcr.io\" rel=\"noopener noreferrer nofollow\"><strong>ghcr.io<\/strong><\/a><strong>)<\/strong>, <strong>GitLab Container Registry<\/strong>, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 <strong>Gitea<\/strong> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0427\u0435\u043c \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f<\/h4>\n<ul>\n<li>\n<p><strong>Docker Hub<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043b\u044e\u0441\u044b: \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0447\u0430\u0442\u044c, \u043c\u043d\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0431\u0440\u0430\u0437\u043e\u0432.  <\/p>\n<\/li>\n<li>\n<p>\u041c\u0438\u043d\u0443\u0441\u044b: \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0445 \u043f\u043b\u0430\u043d\u0430\u0445 (\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0438 \u043e\u0431\u044a\u0451\u043c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f), \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Self-hosted (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Harbor)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043b\u044e\u0441\u044b: \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u044c, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0438\u043d\u0443\u0441\u044b: \u043d\u0443\u0436\u043d\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Git-\u0445\u043e\u0441\u0442\u0438\u043d\u0433\u0438 (GHCR\/GitLab \u0438 \u0434\u0440.)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043b\u044e\u0441\u044b: \u043e\u0431\u0440\u0430\u0437\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0440\u044f\u0434\u043e\u043c \u0441 \u043a\u043e\u0434\u043e\u043c, \u0443\u0434\u043e\u0431\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f, \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 CI\/CD.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0438\u043d\u0443\u0441\u044b: \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u0438 \u0435\u0451 \u043b\u0438\u043c\u0438\u0442\u0430\u043c.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>\u041a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/h4>\n<ol>\n<li>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0437 \u0438\u0437 <code>Dockerfile<\/code> \u2014 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u0432 CI\/CD.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0435 \u0442\u0435\u0433:<\/p>\n<ul>\n<li>\n<p><strong>\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439<\/strong> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0435\u0440\u0441\u0438\u044f <code>1.2.3<\/code> \u0438\u043b\u0438 SHA \u043a\u043e\u043c\u043c\u0438\u0442\u0430),<\/p>\n<\/li>\n<li>\n<p><strong>\u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0438\u0439<\/strong> (<code>latest<\/code>).   \u0425\u043e\u0440\u043e\u0448\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>\u043e\u0431\u0430 \u0442\u0435\u0433\u0430<\/strong>: \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u043e\u0441\u0442\u0438 \u0438 <code>latest<\/code> \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0437 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 (<code>docker push<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043a\u0430\u043a <code>git push<\/code>, \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437).<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 <code>docker-compose.yml<\/code> \u0438 \u0432\u043c\u0435\u0441\u0442\u043e <code>build: .<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0435 <code>image:<\/code>.   \u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>\u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0435\u0433<\/strong> \u0438\u043b\u0438 <strong>\u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442<\/strong> (<code>@sha256:\u2026<\/code>), \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e <code>latest<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u042f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0441\u0432\u043e\u0439 git-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u0431\u0430\u0437\u0435 <strong>Gitea<\/strong> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043a\u043e\u0434\u0430, \u0438 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432. \u041d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0435\u0435\u0441\u0442\u0440\u043e\u043c \u043e\u0442 GitHub \u2014 <strong>GHCR (<\/strong><a href=\"http:\/\/ghcr.io\" rel=\"noopener noreferrer nofollow\"><strong>ghcr.io<\/strong><\/a><strong>)<\/strong>.  <br \/> \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e self-hosted-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u2014 \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0438 \u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u044e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.<\/p>\n<hr\/>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 GitHub: <a href=\"https:\/\/github.com\/proDreams\/tempProject\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/proDreams\/tempProject<\/a>.<\/p>\n<p>\u042d\u0442\u043e Telegram-\u0431\u043e\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u043b\u044e\u0431\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u043c <strong>\u00abHello World!\u00bb<\/strong>.  <br \/> \u041e\u043d \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u0448\u0430\u0433\u0438 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0430 \u0432\u044b \u043f\u043e\u0442\u043e\u043c \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u043e\u0434 \u0441\u0432\u043e\u0439.<\/p>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c, \u0447\u0442\u043e \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438.<\/p>\n<h4>Dockerfile<\/h4>\n<p><code>Dockerfile<\/code> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code>FROM python:3.13-slim    WORKDIR \/code    COPY requirements.txt \/code    RUN pip install --upgrade pip &amp;&amp; pip install -r requirements.txt    COPY . \/code    CMD [ \"python\", \".\/main.py\" ]<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0448\u0430\u0433 \u0437\u0430 \u0448\u0430\u0433\u043e\u043c:<\/p>\n<ol>\n<li>\n<p><code><strong>FROM python:3.13-slim<\/strong><\/code>   \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 \u0441 Python 3.13 \u043d\u0430 \u043e\u0431\u043b\u0435\u0433\u0447\u0451\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 (<code>slim<\/code>). \u0422\u0430\u043a\u043e\u0439 \u043e\u0431\u0440\u0430\u0437 \u0432\u0435\u0441\u0438\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p><code><strong>WORKDIR \/code<\/strong><\/code>   \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430. \u0412\u0441\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0438\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p><code><strong>COPY requirements.txt \/code<\/strong><\/code>   \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0448\u0430\u0433\u043e\u043c, \u0447\u0442\u043e\u0431\u044b Docker \u043c\u043e\u0433 \u0437\u0430\u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0438 \u043d\u0435 \u0441\u0442\u0430\u0432\u0438\u043b \u0438\u0445 \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p><code><strong>RUN pip install --upgrade pip &amp;&amp; pip install -r requirements.txt<\/strong><\/code>   \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c <code>pip<\/code> \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0437 <code>requirements.txt<\/code>.   \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0448\u0430\u0433\u0443, \u0435\u0441\u043b\u0438 <code>requirements.txt<\/code> \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f, \u044d\u0442\u043e\u0442 \u044d\u0442\u0430\u043f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d (Docker \u0432\u043e\u0437\u044c\u043c\u0451\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043a\u0435\u0448\u0430).<\/p>\n<\/li>\n<li>\n<p><code><strong>COPY . \/code<\/strong><\/code>   \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p><code><strong>CMD [\"python\", \".\/<\/strong><\/code><a href=\"http:\/\/main.py\" rel=\"noopener noreferrer nofollow\"><code><strong>main.py<\/strong><\/code><\/a><code><strong>\"]<\/strong><\/code>   \u0417\u0430\u0434\u0430\u0451\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u2014 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u0448\u0435\u0433\u043e Telegram-\u0431\u043e\u0442\u0430.   \u0412\u0430\u0436\u043d\u043e: <code>CMD<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 (<code>docker run ...<\/code>), \u0430 \u0432\u043e\u0442 <code>ENTRYPOINT<\/code> \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u042d\u0442\u043e\u0442 <code>Dockerfile<\/code> \u0443\u0436\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.<\/p>\n<h4>docker-compose.yaml<\/h4>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u0444\u0430\u0439\u043b <code>docker-compose.yaml<\/code> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"yaml\">services:     test-bot:       build: .       container_name: test-bot       environment:         - BOT_TOKEN=${BOT_TOKEN}<\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441 <code><strong>test-bot<\/strong><\/code>, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e Docker <strong>\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0437 \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u0430\u043f\u043a\u0438<\/strong> (<code>build: .<\/code>) \u043f\u043e <code>Dockerfile<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u0438\u043c\u044f <code><strong>test-bot<\/strong><\/code>. \u042d\u0442\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u043f\u043e\u0438\u0441\u043a \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u043b\u043e\u0433\u043e\u0432 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code><strong>BOT_TOKEN<\/strong><\/code>.   \u0415\u0451 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0435\u0440\u0451\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u043b\u0438\u0431\u043e \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0445\u043e\u0441\u0442\u0435,<\/p>\n<\/li>\n<li>\n<p>\u043b\u0438\u0431\u043e \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 <code><strong>.env<\/strong><\/code>, \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0440\u044f\u0434\u043e\u043c \u0441 <code>docker-compose.yaml<\/code>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<blockquote>\n<p>\u0421\u043e\u0432\u0435\u0442: \u0444\u0430\u0439\u043b <code>.env<\/code> \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u0439.  <br \/>   \u0412 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0435\u0433\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442, \u0430 \u0434\u0435\u043b\u0430\u044e\u0442 <code>.env.example<\/code> \u0441 \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0434\u0440\u0443\u0433\u0438\u043c \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u0430\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043d\u0443\u0436\u043d\u044b.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0437\u0436\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c CI\/CD, \u0441\u0442\u0440\u043e\u0447\u043a\u0443 <code>build: .<\/code> \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043d\u0430 <code><strong>image: ...<\/strong><\/code>, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 \u043e\u0431\u0440\u0430\u0437.<\/p>\n<h4>main.py<\/h4>\n<p>\u041a\u043e\u0434 \u0431\u043e\u0442\u0430:<\/p>\n<pre><code class=\"python\">import asyncio   import os    from aiogram import Dispatcher, Bot   from aiogram.types import Message   from dotenv import load_dotenv    load_dotenv()    async def send_message(message: Message) -&gt; None:       await message.answer(text=\"Hello World!\")    async def start() -&gt; None:       bot = Bot(token=os.getenv('BOT_TOKEN'))       dp = Dispatcher()        dp.message.register(send_message)        try:           await dp.start_polling(bot)       finally:           await bot.session.close()     if __name__  \"__main__\":       asyncio.run(start())<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:<\/p>\n<ul>\n<li>\n<p><code><strong>load_dotenv()<\/strong><\/code>   \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 <code>.env<\/code>.   \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. \u0412 Docker Compose \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u0437 \u0441\u0435\u043a\u0446\u0438\u0438 <code>environment<\/code> \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 <code>env_file<\/code>.   \u0422\u043e \u0435\u0441\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u044d\u0442\u043e\u0442 \u0432\u044b\u0437\u043e\u0432 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u0435\u043d, \u043d\u043e \u0438 \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/strong>   \u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>send_message<\/code> \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u043b\u044e\u0431\u043e\u0435 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0444\u0440\u0430\u0437\u043e\u0439 <strong>\u00abHello World!\u00bb<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <\/strong><code><strong>start()<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 <code>Bot<\/code> \u0441 \u0442\u043e\u043a\u0435\u043d\u043e\u043c \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>BOT_TOKEN<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 <code>Dispatcher<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f <strong>\u0432\u0441\u0435\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/strong> (<code>dp.message.register(send_message)<\/code>).<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0417\u0430\u043f\u0443\u0441\u043a long polling<\/strong>   <code>dp.start_polling(bot)<\/code> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c long polling \u2014 \u0431\u043e\u0442 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u044b Telegram \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b<\/strong>   \u0412 \u0431\u043b\u043e\u043a\u0435 <code>finally<\/code> \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f HTTP-\u0441\u0435\u0441\u0441\u0438\u044f \u0431\u043e\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u00ab\u0432\u0438\u0441\u044f\u0447\u0438\u0445\u00bb \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0417\u0430\u043f\u0443\u0441\u043a \u0438\u0437 \u0444\u0430\u0439\u043b\u0430<\/strong>   <code>if <strong>name<\/strong>  \"__main__\": <\/code><a href=\"http:\/\/asyncio.run\" rel=\"noopener noreferrer nofollow\"><code>asyncio.run<\/code><\/a><code>(start())<\/code> \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u0431\u043e\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0430 \u043d\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0435 \u0435\u0433\u043e \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0443\u043b\u044c.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>Workflow \u0441\u0431\u043e\u0440\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u0430<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435. \u041d\u0430\u0448\u0430 \u0446\u0435\u043b\u044c \u2014 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Workflow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 <strong>\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c Docker-\u043e\u0431\u0440\u0430\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 GitHub<\/strong>.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f <strong>GitHub Actions<\/strong> \u2014 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0432 GitHub \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u0434\u043b\u044f CI\/CD. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0443\u0448\u0435 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 (\u0438\u043b\u0438 \u043f\u043e \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c).<\/p>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ul>\n<li>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code><strong>.github<\/strong><\/code> \u2014 \u0437\u0434\u0435\u0441\u044c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432\u0441\u0451, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 GitHub.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0451 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0430\u043f\u043a\u0443 <code><strong>workflows<\/strong><\/code> \u2014 \u0438\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c GitHub Actions \u0438\u0449\u0435\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0444\u0430\u0439\u043b <code><strong>build_and_deploy.yaml<\/strong><\/code>.   \u0412 \u043d\u0451\u043c \u043c\u044b \u043e\u043f\u0438\u0448\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u043e \u0441\u0431\u043e\u0440\u043a\u0435 \u0438 \u0434\u0435\u043f\u043b\u043e\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<h4>build_and_deploy.yaml<\/h4>\n<p>\u0424\u0430\u0439\u043b Workflow \u0446\u0435\u043b\u0438\u043a\u043e\u043c:<\/p>\n<pre><code class=\"yaml\">name: Build and Deploy Project    on:     push:       branches:         - main    permissions:     packages: write     contents: read    jobs:     build-and-push:       runs-on: ubuntu-latest        steps:         - name: Checkout repository           uses: actions\/checkout@v4          - name: Set up Docker Buildx           uses: docker\/setup-buildx-action@v3          - name: Log in to GitHub Container Registry           uses: docker\/login-action@v3           with:             registry: ghcr.io             username: ${{ github.actor }}             password: ${{ secrets.GITHUB_TOKEN }}          - name: Build and push Docker image           uses: docker\/build-push-action@v6           with:             context: .             push: true             cache-from: type=registry,ref=ghcr.io\/prodreams\/tempproject:latest             cache-to: type=inline             tags: |               ghcr.io\/prodreams\/tempproject:latest                 ghcr.io\/prodreams\/tempproject:${{ github.sha }}<\/code><\/pre>\n<h4>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/h4>\n<ul>\n<li>\n<p><code><strong>name<\/strong><\/code>   \u041f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 Workflow. \u041e\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 <strong>Actions<\/strong> \u043d\u0430 GitHub.<\/p>\n<\/li>\n<li>\n<p><code><strong>on.push.branches: main<\/strong><\/code>   \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Workflow \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0443\u0448\u0435 \u0432 \u0432\u0435\u0442\u043a\u0443 <strong>main<\/strong>. \u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u0435\u0442\u043a\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430, \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u0435 <code>main<\/code> \u043d\u0430 \u043d\u0443\u0436\u043d\u0443\u044e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>production<\/code>).<\/p>\n<\/li>\n<li>\n<p><code><strong>permissions<\/strong><\/code>   \u0414\u0430\u0451\u043c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c\u0443 <code>GITHUB_TOKEN<\/code> \u043f\u0440\u0430\u0432\u0430:<\/p>\n<ul>\n<li>\n<p><code>packages: write<\/code> \u2014 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u044b \u0432 GitHub Container Registry,<\/p>\n<\/li>\n<li>\n<p><code>contents: read<\/code> \u2014 \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u0434 \u0438\u0437 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><code><strong>runs-on: ubuntu-latest<\/strong><\/code>   GitHub \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0431\u043e\u0440\u043a\u0443 \u043d\u0430 Linux-\u0440\u0430\u043d\u043d\u0435\u0440\u0435 (\u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 Ubuntu).<\/p>\n<\/li>\n<li>\n<p><strong>Checkout<\/strong>   \u0417\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043e\u0434 \u0432\u0430\u0448\u0435\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u043d\u0430 \u0440\u0430\u043d\u043d\u0435\u0440. \u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e Docker \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u0442 <code>Dockerfile<\/code> \u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>Buildx<\/strong>   \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u0431\u043e\u0440\u043a\u0438 Docker.   \u041e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043c\u0443\u043b\u044c\u0442\u0438\u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u044b \u043f\u043e\u0434 ARM).<\/p>\n<\/li>\n<li>\n<p><strong>Login \u0432 GHCR<\/strong>   \u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0443\u0435\u043c\u0441\u044f \u0432 GitHub Container Registry (<a href=\"http:\/\/ghcr.io\" rel=\"noopener noreferrer nofollow\"><code>ghcr.io<\/code><\/a>) \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e <code>GITHUB_TOKEN<\/code>.<br \/>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u043f\u0443\u0448\u0435 \u0432 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443 <code>403<\/code>, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435:<\/p>\n<ol>\n<li>\n<p>\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 GitHub Actions \u0434\u043b\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443\u0436\u0435\u043d \u043b\u0438 \u0432\u0430\u043c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d (PAT) \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 <code>write:packages<\/code>.<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><strong>Build and push Docker image<\/strong><\/p>\n<ul>\n<li>\n<p><code>context: .<\/code> \u2014 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0437 \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><code>push: true<\/code> \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0437 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440.<\/p>\n<\/li>\n<li>\n<p><code>cache-from<\/code> \/ <code>cache-to<\/code> \u2014 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043a\u0435\u0448, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0431\u044b\u043b\u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435.   (\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 Workflow \u0432\u043f\u0435\u0440\u0432\u044b\u0435, \u043a\u0435\u0448\u0430 \u0435\u0449\u0451 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u2014 \u044d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e).<\/p>\n<\/li>\n<li>\n<p><code>tags<\/code> \u2014 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0437 \u0441\u0440\u0430\u0437\u0443 \u0441 \u0434\u0432\u0443\u043c\u044f \u0442\u0435\u0433\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p><code>latest<\/code> \u2014 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0432\u0435\u0440\u0441\u0438\u044e;<\/p>\n<\/li>\n<li>\n<p><code>${{ github.sha }}<\/code> \u2014 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0435\u0433 \u043f\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0443 (\u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0442\u043e\u0447\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438).<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>\u041e\u0442\u043a\u0443\u0434\u0430 \u0432\u0437\u044f\u0442\u044c \u0430\u0434\u0440\u0435\u0441?<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f Workflow \u043e\u0431\u0440\u0430\u0437 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442\u0441\u044f \u0432 GHCR \u0441 \u0442\u0435\u0433\u0430\u043c\u0438 <code><strong>latest<\/strong><\/code> \u0438 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0445\u044d\u0448\u0435\u043c \u043a\u043e\u043c\u043c\u0438\u0442\u0430 (<code><strong>${{ github.sha }}<\/strong><\/code>).  <br \/> \u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043e\u0431\u0440\u0430\u0437 \u0432 <code>docker-compose.yml<\/code>, \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c <strong>\u043f\u043e\u043b\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0442\u0435\u0433\u043e\u043c<\/strong>.<\/p>\n<p><strong>\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f GHCR:<\/strong>  <\/p>\n<pre><code>ghcr.io\/&lt;\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f_\u0438\u043b\u0438_\u0438\u043c\u044f_\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f&gt;\/&lt;\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u043e\u0431\u0440\u0430\u0437\u0430&gt;:&lt;\u0442\u0435\u0433&gt;<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0430\u0434\u0440\u0435\u0441 (\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u0431\u0440\u0430\u0437 \u0435\u0449\u0451 \u043d\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d):<\/p>\n<ul>\n<li>\n<p><code><strong>ghcr.io\/<\/strong><\/code> \u2014 \u0434\u043e\u043c\u0435\u043d GitHub Container Registry.<\/p>\n<\/li>\n<li>\n<p><code><strong>&lt;\u0438\u043c\u044f_\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f&gt;<\/strong><\/code><strong> \u0438\u043b\u0438 <\/strong><code><strong>&lt;\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f&gt;<\/strong><\/code> \u2014 \u0432\u0430\u0448 \u043b\u043e\u0433\u0438\u043d GitHub \u0438\u043b\u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 (<strong>\u0441\u0442\u0440\u043e\u0433\u043e \u0432 \u043d\u0438\u0436\u043d\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0435<\/strong>).<\/p>\n<\/li>\n<li>\n<p><code><strong>&lt;\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u043e\u0431\u0440\u0430\u0437\u0430&gt;<\/strong><\/code> \u2014 \u043e\u0431\u044b\u0447\u043d\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f (<strong>\u0442\u043e\u0436\u0435 \u0432 \u043d\u0438\u0436\u043d\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0435<\/strong>).<\/p>\n<\/li>\n<li>\n<p><code><strong>:\u0442\u0435\u0433<\/strong><\/code> \u2014 \u0432\u0435\u0440\u0441\u0438\u044f \u043e\u0431\u0440\u0430\u0437\u0430. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c <code>latest<\/code>, <code>1.0.0<\/code>, \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 SHA \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0438\u043b\u0438 <code>${{ github.sha }}<\/code>.<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>\u26a0\ufe0f \u0412\u0430\u0436\u043d\u043e: \u0438\u043c\u044f \u043e\u0431\u0440\u0430\u0437\u0430 (\u0432\u0441\u0451 \u0434\u043e \u0434\u0432\u043e\u0435\u0442\u043e\u0447\u0438\u044f \u0441 \u0442\u0435\u0433\u043e\u043c) \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 <strong>\u043d\u0438\u0436\u043d\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0435<\/strong>, \u0438\u043d\u0430\u0447\u0435 Docker \u0432\u044b\u0434\u0430\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 <code>invalid reference format<\/code>.<\/p>\n<\/blockquote>\n<p>\u0414\u043b\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f <a href=\"https:\/\/github.com\/proDreams\/tempProject\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/proDreams\/tempProject<\/a> \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u0431\u0443\u0434\u0435\u0442:<\/p>\n<pre><code>ghcr.io\/prodreams\/tempproject<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u043f\u043e\u043b\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432:<\/p>\n<pre><code>ghcr.io\/prodreams\/tempproject:latest ghcr.io\/prodreams\/tempproject:${{ github.sha }}<\/code><\/pre>\n<h4>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 GitHub \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Workflow<\/h4>\n<p>\u0424\u0430\u0439\u043b Workflow \u0433\u043e\u0442\u043e\u0432 \u2014 \u043f\u043e\u0440\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.  <br \/> \u041a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043c\u0438\u0442 \u043f\u043e\u043f\u0430\u0434\u0451\u0442 \u043d\u0430 GitHub \u0438 <strong>\u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0440\u0438\u0433\u0433\u0435\u0440<\/strong> (\u0443 \u043d\u0430\u0441 \u2014 \u043f\u0443\u0448 \u0432 \u0432\u0435\u0442\u043a\u0443 <code>main<\/code>), Actions \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435:<\/p>\n<pre><code class=\"bash\">git add .github\/workflows\/build_and_deploy.yaml  git commit -m \"CI\/CD: Build docker image\"  git push<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 <strong>Actions<\/strong>. \u0422\u0430\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0439\u0441\u044f Workflow:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/524\/915\/76e\/52491576e36c506e41912a77e31d1381.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/524\/915\/76e\/52491576e36c506e41912a77e31d1381.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/524\/915\/76e\/52491576e36c506e41912a77e31d1381.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041a\u043b\u0438\u043a\u0430\u0435\u043c \u043f\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u043d\u0438\u0439 (jobs). \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043d\u043e \u043e\u0434\u043d\u043e \u0438 \u043d\u0430 \u043d\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u044c:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/899\/69c\/335\/89969c33574ce8baf90657b7f9881727.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/899\/69c\/335\/89969c33574ce8baf90657b7f9881727.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/899\/69c\/335\/89969c33574ce8baf90657b7f9881727.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u043b\u043e\u0433 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u0417\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433 \u0438, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0439\u0434\u0451\u0442 \u043d\u0435 \u0442\u0430\u043a, \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u0440\u0438\u0447\u0438\u043d\u0443:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d88\/a1c\/cd3\/d88a1ccd30f971070c5d75c7e1a6bb86.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d88\/a1c\/cd3\/d88a1ccd30f971070c5d75c7e1a6bb86.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d88\/a1c\/cd3\/d88a1ccd30f971070c5d75c7e1a6bb86.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0423 \u043d\u0430\u0441 \u0432\u0441\u0451 \u043f\u0440\u043e\u0448\u043b\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u2014 \u043e\u0431\u0440\u0430\u0437 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u0432 \u0440\u0435\u0435\u0441\u0442\u0440.  <br \/> \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0432 \u043f\u0440\u0430\u0432\u043e\u043c \u0431\u043b\u043e\u043a\u0435 <strong>Packages<\/strong> \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043d\u0430\u0448 Docker-\u043e\u0431\u0440\u0430\u0437:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9ed\/282\/7d3\/9ed2827d3ee0dc42f3de04db03e691a7.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/9ed\/282\/7d3\/9ed2827d3ee0dc42f3de04db03e691a7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9ed\/282\/7d3\/9ed2827d3ee0dc42f3de04db03e691a7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043f\u043e \u043f\u0430\u043a\u0435\u0442\u0443, \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e\u0431 \u043e\u0431\u0440\u0430\u0437\u0435:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/71b\/129\/1cf\/71b1291cfd08f7432fe3441bdbe01e06.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/71b\/129\/1cf\/71b1291cfd08f7432fe3441bdbe01e06.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/71b\/129\/1cf\/71b1291cfd08f7432fe3441bdbe01e06.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u0415\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e<\/h4>\n<ul>\n<li>\n<p><strong>Workflow \u043d\u0435 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u043b<\/strong><\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0447\u0442\u043e \u043f\u0443\u0448\u0438\u0442\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u0432\u0435\u0442\u043a\u0443 <code>main<\/code> (\u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0432\u0435\u0442\u043a\u0443 \u0432 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0435),<\/p>\n<\/li>\n<li>\n<p>\u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0444\u0430\u0439\u043b \u043b\u0435\u0436\u0438\u0442 \u0432 <code>.github\/workflows\/...<\/code>,<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043b\u0438 Actions \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u0443\u0448\u0435 \u0432 GHCR<\/strong><\/p>\n<ul>\n<li>\n<p>\u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432 Workflow \u0443\u043a\u0430\u0437\u0430\u043d\u043e <code>permissions: packages: write<\/code>,<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0447\u0442\u043e \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0438\u0437 Actions \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0430,<\/p>\n<\/li>\n<li>\n<p>\u0435\u0441\u043b\u0438 \u043f\u0430\u043a\u0435\u0442 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 \u2014 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u043e\u0431\u0440\u0430\u0437\u0430 \u0432 GHCR \u0438 \u0434\u0432\u0430 \u0442\u0435\u0433\u0430:<\/p>\n<ul>\n<li>\n<p><code><strong>latest<\/strong><\/code> \u2014 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0441\u0431\u043e\u0440\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p><code><strong>${{ github.sha }}<\/strong><\/code> \u2014 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0434\u043b\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0435\u043f\u043b\u043e\u044f.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c Portainer Business Edition<\/h3>\n<p>\u041c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441: \u0437\u0430\u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430 <strong>Business Edition<\/strong>, \u0435\u0441\u043b\u0438 \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u0445\u0432\u0430\u0442\u0430\u043b\u043e \u0432\u0435\u0440\u0441\u0438\u0438 <strong>Community<\/strong>?  <br \/> \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e CE (Community Edition) \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438: \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c Docker-\u0445\u043e\u0441\u0442\u0430\u043c\u0438, \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438 \u0438 \u0441\u0442\u0430\u043a\u0430\u043c\u0438.  <br \/> \u041e\u0434\u043d\u0430\u043a\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong>\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Webhook\u2019\u043e\u0432 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u043a\u043e\u0432 \u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432<\/strong> \u0442\u0430\u043c \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u2014 \u044d\u0442\u043e \u0443\u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b Business Edition.<\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u043d\u043e\u0432\u043e\u0441\u0442\u044c: Business Edition \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c <strong>\u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e<\/strong>, \u043d\u043e \u0441 \u043e\u0434\u043d\u0438\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u2014 <strong>\u043d\u0435 \u0431\u043e\u043b\u0435\u0435 \u0442\u0440\u0451\u0445 Docker-\u0445\u043e\u0441\u0442\u043e\u0432<\/strong> (\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439).  <br \/> \u0414\u043b\u044f \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u0438\u043b\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<h4>\u041a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043b\u044e\u0447<\/h4>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b <strong>Take 3<\/strong>:  <br \/> \ud83d\udc49 <a href=\"https:\/\/www.portainer.io\/take-3\" rel=\"noopener noreferrer nofollow\">https:\/\/www.portainer.io\/take-3<\/a><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d5d\/69b\/452\/d5d69b4528ee5d97db4341635a72e545.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d5d\/69b\/452\/d5d69b4528ee5d97db4341635a72e545.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d5d\/69b\/452\/d5d69b4528ee5d97db4341635a72e545.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0421\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0430. \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0451:<\/p>\n<ul>\n<li>\n<p><strong>\u0418\u043c\u044f \u0438 \u0444\u0430\u043c\u0438\u043b\u0438\u044f<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u042d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u0430\u044f \u043f\u043e\u0447\u0442\u0430<\/strong> \u2014 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0440\u0430\u0431\u043e\u0447\u0443\u044e, \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0443\u0434\u0430 \u043f\u0440\u0438\u0434\u0451\u0442 \u043a\u043b\u044e\u0447.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u043e\u043c\u0435\u0440 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430<\/strong> \u2014 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0442\u0440\u0430\u043d\u0430<\/strong> \u2014 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u00ab\u0420\u043e\u0441\u0441\u0438\u044f\u00bb (\u0435\u0441\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435).<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043b\u0438 \u0432\u044b Portainer CE?<\/strong> \u2014 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u043c \u00ab\u0414\u0430\u00bb.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/strong> \u2014 \u0432 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u00abDocker Standalone\u00bb.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u043a \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 Portainer?<\/strong> \u2014 \u044f \u0443\u043a\u0430\u0437\u0430\u043b \u00ab\u0414\u043b\u044f \u0434\u043e\u043c\u0430\u00bb.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u043a \u0443\u0437\u043d\u0430\u043b\u0438 \u043e Portainer<\/strong> \u2014 \u0432\u044b\u0431\u0438\u0440\u0430\u0439\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442.<\/p>\n<\/li>\n<li>\n<p>\u0418 \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0433\u0430\u043b\u043e\u0447\u043a\u0443 \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u044f \u0441 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u043e\u043d\u043d\u044b\u043c \u0441\u043e\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u00abSubmit\u00bb \u0436\u0434\u0451\u043c \u043f\u0438\u0441\u044c\u043c\u043e \u043d\u0430 \u043f\u043e\u0447\u0442\u0443 \u0441 \u043a\u043e\u0434\u043e\u043c \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438.<\/p>\n<h4>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 Portainer CE \u0434\u043e BE<\/h4>\n<p>\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c Portainer \u0434\u043e Business Edition \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 <a href=\"http:\/\/DockerHosting.ru\" rel=\"noopener noreferrer nofollow\">DockerHosting.ru<\/a>, \u0442\u043e \u043f\u0440\u0435\u0434\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Portainer \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443:<\/p>\n<pre><code>https:\/\/&lt;ip_\u0441\u0435\u0440\u0432\u0435\u0440\u0430&gt;:9000\/<\/code><\/pre>\n<p>\u0412 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u043b\u0435\u0432\u043e\u043c \u0443\u0433\u043b\u0443, \u043d\u0430\u0434 \u043b\u043e\u0433\u043e\u0442\u0438\u043f\u043e\u043c, \u0435\u0441\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0430 <strong>\u00abUpgrade to Business Edition\u00bb<\/strong>. \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u0435\u0451 \u2014 \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043e\u043a\u043d\u043e \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u043a\u043b\u044e\u0447\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/635\/691\/064\/6356910647f9e3c2a149dda9a09d50ae.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/635\/691\/064\/6356910647f9e3c2a149dda9a09d50ae.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/635\/691\/064\/6356910647f9e3c2a149dda9a09d50ae.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <strong>\u00abStart upgrade\u00bb<\/strong>.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0447\u043d\u0451\u0442\u0441\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f. \u041a\u043e\u0433\u0434\u0430 \u043e\u043d \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f, \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442 \u0432\u0430\u0441 \u0441\u043d\u043e\u0432\u0430 \u0432\u043e\u0439\u0442\u0438 \u0432 \u0430\u043a\u043a\u0430\u0443\u043d\u0442:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0a7\/37c\/40d\/0a737c40dc145594354a7924efac9873.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0a7\/37c\/40d\/0a737c40dc145594354a7924efac9873.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0a7\/37c\/40d\/0a737c40dc145594354a7924efac9873.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<blockquote>\n<p>\u26a1 \u0412\u0430\u0436\u043d\u043e: \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0434\u043e BE \u0432\u0430\u0448\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u0441\u0442\u0435\u043a\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 <strong>\u043d\u0435 \u043f\u0440\u043e\u043f\u0430\u0434\u0443\u0442<\/strong>.  <br \/>   Portainer \u043f\u0440\u043e\u0441\u0442\u043e \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Webhook\u2019\u0438.<\/p>\n<\/blockquote>\n<hr\/>\n<h3>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0440\u0435\u0435\u0441\u0442\u0440\u0430 \u0432 Portainer<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043a Portainer \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0440\u0435\u0435\u0441\u0442\u0440 GitHub. \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0434\u0435\u043f\u043b\u043e\u0435 Portainer \u043c\u043e\u0433 \u0441\u0430\u043c <strong>\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0435\u0441\u0442\u0440\u0435<\/strong> \u0438 <strong>\u0441\u043a\u0430\u0447\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437<\/strong>.<\/p>\n<p>\u0412 \u043b\u0435\u0432\u043e\u043c \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 <strong>Registries<\/strong> \u2014 \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u0445 \u0440\u0435\u0435\u0441\u0442\u0440\u043e\u0432:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac5\/6a7\/d16\/ac56a7d16befeb952315cb9c7c5b8cfe.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ac5\/6a7\/d16\/ac56a7d16befeb952315cb9c7c5b8cfe.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac5\/6a7\/d16\/ac56a7d16befeb952315cb9c7c5b8cfe.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 <strong>Add Registry<\/strong>. \u0412\u044b \u043f\u043e\u043f\u0430\u0434\u0451\u0442\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ba0\/a26\/105\/ba0a26105925d4289116f02ffdc8d14b.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ba0\/a26\/105\/ba0a26105925d4289116f02ffdc8d14b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ba0\/a26\/105\/ba0a26105925d4289116f02ffdc8d14b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0418\u0437 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c <strong>GitHub<\/strong> (\u0434\u043b\u044f GitHub Container Registry):<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/397\/6bc\/59b\/3976bc59b2b0e7da82a27fee3db52df7.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/397\/6bc\/59b\/3976bc59b2b0e7da82a27fee3db52df7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/397\/6bc\/59b\/3976bc59b2b0e7da82a27fee3db52df7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u043b\u044f:<\/p>\n<ul>\n<li>\n<p><strong>Name<\/strong> \u2014 \u043b\u044e\u0431\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>github<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Username<\/strong> \u2014 \u0432\u0430\u0448 \u043b\u043e\u0433\u0438\u043d GitHub.<\/p>\n<\/li>\n<li>\n<p><strong>Personal Access Token<\/strong> \u2014 \u0432\u0430\u0448 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d GitHub.   \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0434\u0435\u0441\u044c: \ud83d\udc49 <a href=\"https:\/\/github.com\/settings\/tokens\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/settings\/tokens<\/a><\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>\u0414\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432\u0430 <strong>read:packages<\/strong>.  <br \/>   \u041d\u0435 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043b\u0438\u0448\u043d\u0438\u0445 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439: Portainer \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u044b, \u0430 \u043f\u0443\u0448\u0438\u0442 \u0438\u0445 \u0432\u0430\u0448 CI.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u044b \u0432\u0435\u0440\u043d\u0451\u0442\u0435\u0441\u044c \u043a \u0441\u043f\u0438\u0441\u043a\u0443 \u0440\u0435\u0435\u0441\u0442\u0440\u043e\u0432, \u0433\u0434\u0435 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a GitHub:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/848\/aad\/3e0\/848aad3e02273835a45f2a85602b4250.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/848\/aad\/3e0\/848aad3e02273835a45f2a85602b4250.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/848\/aad\/3e0\/848aad3e02273835a45f2a85602b4250.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f<\/h4>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0431\u0440\u0430\u0437\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0439 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0442\u043e\u043a\u0435\u043d \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u0442\u043e\u0439 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043a \u043f\u0430\u043a\u0435\u0442\u0430\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f Portainer \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 <strong>\u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0430<\/strong> (\u043e\u0431\u044b\u0447\u043d\u043e read-only).<\/p>\n<\/li>\n<li>\n<p>\u26a0\ufe0f \u041d\u0435 \u043f\u0443\u0442\u0430\u0439\u0442\u0435 <strong>Personal Access Token<\/strong> \u0441 <code>GITHUB_TOKEN<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 GitHub Actions.   <code>GITHUB_TOKEN<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 CI, \u0430 \u0434\u043b\u044f Portainer \u043d\u0443\u0436\u0435\u043d \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 PAT.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 GitHub Container Registry \u0432 Portainer CE<\/h4>\n<p>\u0412 <strong>Portainer Community Edition<\/strong> \u043d\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0434\u043b\u044f GitHub, \u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0435\u0441\u0442\u0440 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0435\u0437 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.  <br \/> \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c <strong>Custom registry<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d8d\/b66\/e74\/d8db66e74be551941776ff0b03ad0145.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d8d\/b66\/e74\/d8db66e74be551941776ff0b03ad0145.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d8d\/b66\/e74\/d8db66e74be551941776ff0b03ad0145.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u043e\u043b\u044f:<\/p>\n<ul>\n<li>\n<p><strong>Name<\/strong> \u2014 \u043b\u044e\u0431\u043e\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>GitHub<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Registry URL<\/strong> \u2014 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c <a href=\"http:\/\/ghcr.io\" rel=\"noopener noreferrer nofollow\"><code>ghcr.io<\/code><\/a>.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c <strong>Authentication<\/strong> \u0438 \u0432\u0432\u043e\u0434\u0438\u043c:<\/p>\n<ul>\n<li>\n<p><strong>Username<\/strong> \u2014 \u0432\u0430\u0448 \u043b\u043e\u0433\u0438\u043d GitHub,<\/p>\n<\/li>\n<li>\n<p><strong>Password\/Token<\/strong> \u2014 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d (PAT). \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0434\u0435\u0441\u044c: \ud83d\udc49 <a href=\"https:\/\/github.com\/settings\/tokens\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/settings\/tokens<\/a>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<blockquote>\n<p>\u0414\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0430\u0432\u0430 <strong>read:packages<\/strong>.  <br \/>   \u041f\u043e\u043c\u043d\u0438\u0442\u0435: \u044d\u0442\u043e\u0442 \u0442\u043e\u043a\u0435\u043d \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 <code>GITHUB_TOKEN<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 GitHub Actions. \u0417\u0434\u0435\u0441\u044c \u043d\u0443\u0436\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e <strong>\u0432\u0430\u0448 PAT<\/strong>.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f <strong>Add registry<\/strong> \u0440\u0435\u0435\u0441\u0442\u0440 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e.<\/p>\n<hr\/>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0442\u0435\u043a\u0430 \u0432 Portainer<\/h3>\n<p>\u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0443\u0436\u0435 <a href=\"https:\/\/pressanybutton.ru\/post\/primenenie-docker\/bystryj-deploj-bota-i-ne-tolko-na-docker-hostinge-s-portainer\/#deploj-proekta\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0442\u0435\u043a \u0438\u0437 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/a>.  <br \/> \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b <code><strong>docker-compose.yml<\/strong><\/code> \u2014 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0432 \u0435\u0433\u043e.<\/p>\n<h4>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 docker-compose.yml<\/h4>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0442\u0430\u043a:<\/p>\n<pre><code class=\"yaml\">services:     test-bot:       build: .       container_name: test-bot       environment:         - BOT_TOKEN=${BOT_TOKEN}<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e (<code>build: .<\/code>).  <br \/> \u041d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u0430.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0442\u044f\u043d\u0443\u0442\u044c \u043e\u0431\u0440\u0430\u0437 \u0438\u0437 \u0440\u0435\u0435\u0441\u0442\u0440\u0430, \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 <code>build: .<\/code> \u043d\u0430 <code><strong>image:<\/strong><\/code> \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0441 \u0442\u0435\u0433\u043e\u043c:<\/p>\n<pre><code class=\"yaml\">services:     test-bot:       image: ghcr.io\/prodreams\/tempproject:latest       container_name: test-bot       environment:         - BOT_TOKEN=${BOT_TOKEN}<\/code><\/pre>\n<h4>\u0421\u0442\u0435\u043a \u0432 Portainer<\/h4>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u0432 Portainer \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b <strong>Stacks<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6ab\/aec\/8cd\/6abaec8cd27fce396ac4ed3d0554d8c6.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/6ab\/aec\/8cd\/6abaec8cd27fce396ac4ed3d0554d8c6.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6ab\/aec\/8cd\/6abaec8cd27fce396ac4ed3d0554d8c6.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <strong>Add stack<\/strong>.  <br \/> \u041e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0442\u0435\u043a\u0430. \u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 <strong>Web editor<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/aaa\/cb1\/77d\/aaacb177d65fcf45f7f1cedfff045fcb.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/aaa\/cb1\/77d\/aaacb177d65fcf45f7f1cedfff045fcb.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/aaa\/cb1\/77d\/aaacb177d65fcf45f7f1cedfff045fcb.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0432\u0435\u0440\u0445\u0443 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0435\u043a\u0430. \u0412 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e <code>test-bot<\/code>.  <br \/> \u041d\u0438\u0436\u0435 \u0432 \u043f\u043e\u043b\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043d\u0430\u0448\u0435\u0433\u043e <code>docker-compose.yml<\/code>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/755\/5ba\/cc2\/7555bacc20e3975b669f5745f66faee4.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/755\/5ba\/cc2\/7555bacc20e3975b669f5745f66faee4.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/755\/5ba\/cc2\/7555bacc20e3975b669f5745f66faee4.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0435\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u043d\u0438\u0437 \u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044c <strong>Create a Stack webhook<\/strong>.  <br \/> \u042d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u0434\u043b\u044f \u0432\u0435\u0431\u0445\u0443\u043a\u0430 \u2014 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043d\u0435\u0451 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u0437 CI\/CD, \u0447\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <strong>Environment variables<\/strong> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code><strong>BOT_TOKEN<\/strong><\/code> \u2014 \u0441\u044e\u0434\u0430 \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043a\u0435\u043d \u043d\u0430\u0448\u0435\u0433\u043e Telegram-\u0431\u043e\u0442\u0430.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0436\u043c\u0451\u043c <strong>Deploy the stack<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/313\/1bf\/49e\/3131bf49e8b03fd42bc4b63a3127d271.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/313\/1bf\/49e\/3131bf49e8b03fd42bc4b63a3127d271.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/313\/1bf\/49e\/3131bf49e8b03fd42bc4b63a3127d271.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0427\u0435\u0440\u0435\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434 \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u043a\u043e\u0432:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b62\/a99\/c47\/b62a99c4734b3c2e6217ca4fd5c471fd.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/b62\/a99\/c47\/b62a99c4734b3c2e6217ca4fd5c471fd.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b62\/a99\/c47\/b62a99c4734b3c2e6217ca4fd5c471fd.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0431\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/17e\/e61\/414\/17ee614140b8a38277a34ef5c8bac497.png\" width=\"1600\" height=\"2298\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/17e\/e61\/414\/17ee614140b8a38277a34ef5c8bac497.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/17e\/e61\/414\/17ee614140b8a38277a34ef5c8bac497.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<blockquote>\n<p>\u26a1 \u0415\u0441\u043b\u0438 \u0431\u043e\u0442 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f, \u0437\u0430\u0433\u043b\u044f\u043d\u0438\u0442\u0435 \u0432 \u043b\u043e\u0433\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u2014 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u043e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0432\u0432\u0435\u0434\u0451\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.<\/p>\n<\/blockquote>\n<h4>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 \u0432\u0435\u0431\u0445\u0443\u043a\u0430<\/h4>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430 \u2014 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Workflow \u0434\u0435\u043f\u043b\u043e\u044f \u2014 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0430\u0434\u0440\u0435\u0441 <strong>Webhook<\/strong> \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430.<\/p>\n<p>\u041d\u0430\u0445\u043e\u0434\u044f\u0441\u044c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <strong>Stacks<\/strong>, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043d\u0430\u0448 \u0441\u0442\u0435\u043a \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0435\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/760\/02f\/91d\/76002f91da9dd614002b5a13bf283dcd.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/760\/02f\/91d\/76002f91da9dd614002b5a13bf283dcd.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/760\/02f\/91d\/76002f91da9dd614002b5a13bf283dcd.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <strong>Editor<\/strong>, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.  <br \/> \u0412 \u0431\u043b\u043e\u043a\u0435 <strong>Webhooks<\/strong> \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u0432\u0435\u0431\u0445\u0443\u043a\u0430.<\/p>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <strong>Copy link<\/strong>, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0451:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/133\/fc4\/2d6\/133fc42d6cc9f16665c4f0e860fba241.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/133\/fc4\/2d6\/133fc42d6cc9f16665c4f0e860fba241.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/133\/fc4\/2d6\/133fc42d6cc9f16665c4f0e860fba241.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u042d\u0442\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430\u043c \u0432 CI\/CD Workflow: \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043d\u0435\u0451 \u0437\u0430\u043f\u0440\u043e\u0441, \u0447\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0438 \u043d\u043e\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043a\u0430\u0445.<\/p>\n<hr\/>\n<h3>Workflow \u0434\u0435\u043f\u043b\u043e\u044f<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 \u2014 \u0434\u0435\u043f\u043b\u043e\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 <strong>Webhook Portainer<\/strong> \u0432 CI\/CD.<\/p>\n<h4>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u043a\u0440\u0435\u0442 \u0432 GitHub Actions<\/h4>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c Workflow, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u0432\u0435\u0431\u0445\u0443\u043a\u0430 \u0432 \u0441\u0435\u043a\u0440\u0435\u0442\u0435 GitHub.  <br \/> \u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u043f\u043e \u0434\u0432\u0443\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c:<\/p>\n<ul>\n<li>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0451\u0442 \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f;<\/p>\n<\/li>\n<li>\n<p>\u0435\u0451 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u0438\u0434\u043d\u043e \u0432 \u043b\u043e\u0433\u0430\u0445 Workflow.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub \u0438 \u0437\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b <strong>Settings<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/634\/a78\/4f1\/634a784f1173d28644a42b52340727af.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/634\/a78\/4f1\/634a784f1173d28644a42b52340727af.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/634\/a78\/4f1\/634a784f1173d28644a42b52340727af.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0421\u043b\u0435\u0432\u0430 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c <strong>Secrets and variables \u2192 Actions<\/strong>. \u041e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u043c\u0438:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b66\/7e6\/585\/b667e65854c8ed7def78a42e80351c83.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/b66\/7e6\/585\/b667e65854c8ed7def78a42e80351c83.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b66\/7e6\/585\/b667e65854c8ed7def78a42e80351c83.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u0437\u0435\u043b\u0451\u043d\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 <strong>New repository secret<\/strong>.<\/p>\n<p>\u0412 \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0435\u0439\u0441\u044f \u0444\u043e\u0440\u043c\u0435:<\/p>\n<ul>\n<li>\n<p>\u0432 \u043f\u043e\u043b\u0435 <strong>Name<\/strong> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u0430 \u2014 <code>PORTAINER_WEBHOOK_URL<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0432 \u043f\u043e\u043b\u0435 <strong>Secret<\/strong> \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0440\u0430\u043d\u0435\u0435 \u0441\u0441\u044b\u043b\u043a\u0443 \u0432\u0435\u0431\u0445\u0443\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d17\/012\/703\/d17012703623802606f2f79db957481a.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d17\/012\/703\/d17012703623802606f2f79db957481a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d17\/012\/703\/d17012703623802606f2f79db957481a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <strong>Add secret<\/strong> \u2014 \u0442\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e\u0442 \u0441\u0435\u043a\u0440\u0435\u0442 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 Workflow:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a63\/821\/b0a\/a63821b0ad48608fbf16203b763a05ce.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a63\/821\/b0a\/a63821b0ad48608fbf16203b763a05ce.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a63\/821\/b0a\/a63821b0ad48608fbf16203b763a05ce.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<blockquote>\n<p>\u26a1 \u0421\u043e\u0432\u0435\u0442: \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0445\u0440\u0430\u043d\u044f\u0442 \u0432 \u043a\u043e\u0434\u0435 Workflow \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e.  <br \/>   \u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0437\u0430\u043a\u043e\u043c\u043c\u0438\u0442\u0438\u0442\u0435 \u0441\u0441\u044b\u043b\u043a\u0443 \u0432\u0435\u0431\u0445\u0443\u043a\u0430 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043b\u044e\u0431\u043e\u0439 \u0441\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<\/blockquote>\n<h4>\u0414\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c build_and_deploy.yaml<\/h4>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u0444\u0430\u0439\u043b <code><strong>build_and_deploy.yaml<\/strong><\/code> \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 (job), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f <strong>\u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u0430<\/strong>.  <br \/> \u041e\u043d\u0430 \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u0432\u0435\u0431\u0445\u0443\u043a, \u0447\u0442\u043e\u0431\u044b Portainer \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u0442\u044f\u043d\u0443\u043b \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>\u041d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441 <code>build-and-push<\/code> \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u044b\u0439 \u0431\u043b\u043e\u043a <code>deploy<\/code>:<\/p>\n<pre><code class=\"yaml\">deploy:     runs-on: ubuntu-latest      needs: build-and-push      steps:       - name: Trigger Portainer webhook         env:           PORTAINER_WEBHOOK_URL: ${{ secrets.PORTAINER_WEBHOOK_URL }}         run: curl -fsS -m 30 -X POST \"$PORTAINER_WEBHOOK_URL\"<\/code><\/pre>\n<h3>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/h3>\n<ul>\n<li>\n<p><code><strong>needs: build-and-push<\/strong><\/code>   \u042d\u0442\u0430 \u0441\u0442\u0440\u043e\u0447\u043a\u0430 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 GitHub Actions:   <em>\u00ab\u0417\u0430\u043f\u0443\u0441\u0442\u0438 \u044d\u0442\u043e\u0442 job \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f <\/em><code><em>build-and-push<\/em><\/code><em>\u00bb.<\/em>   \u0422\u043e \u0435\u0441\u0442\u044c \u0434\u0435\u043f\u043b\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043e\u0431\u0440\u0430\u0437 \u0441\u043e\u0431\u0440\u0430\u043b\u0441\u044f \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0441\u044f \u0432 \u0440\u0435\u0435\u0441\u0442\u0440.<\/p>\n<\/li>\n<li>\n<p><code><strong>env<\/strong><\/code> \u0412 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code>PORTAINER_WEBHOOK_URL<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0435\u043a\u0440\u0435\u0442\u0430 \u0438\u0437 GitHub (<code>${{ secrets.PORTAINER_WEBHOOK_URL }}<\/code>). \u0422\u0430\u043a \u043c\u044b \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u0432\u0435\u0431\u0445\u0443\u043a\u0430 \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0432\u0438\u0434\u0435.<\/p>\n<\/li>\n<li>\n<p><code><strong>curl -fsS -m 30 -X POST \"$PORTAINER_WEBHOOK_URL\"<\/strong><\/code>   \u042d\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 HTTP POST-\u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0432\u0435\u0431\u0445\u0443\u043a Portainer.   \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<ul>\n<li>\n<p><code>-f<\/code> \u2014 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u0435\u0441\u043b\u0438 \u0441\u0442\u0430\u0442\u0443\u0441-\u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430 \u2265 400;<\/p>\n<\/li>\n<li>\n<p><code>-sS<\/code> \u2014 \u0442\u0438\u0445\u0438\u0439 \u0440\u0435\u0436\u0438\u043c \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u043b\u043e\u0433\u043e\u0432, \u043d\u043e \u0441 \u0432\u044b\u0432\u043e\u0434\u043e\u043c \u043e\u0448\u0438\u0431\u043e\u043a;<\/p>\n<\/li>\n<li>\n<p><code>-m 30<\/code> \u2014 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f 30 \u0441\u0435\u043a.;<\/p>\n<\/li>\n<li>\n<p><code>-X POST<\/code> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c POST-\u0437\u0430\u043f\u0440\u043e\u0441;<\/p>\n<\/li>\n<li>\n<p><code>\"$PORTAINER_WEBHOOK_URL\"<\/code> \u2014 \u0441\u0430\u043c\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u0432\u0435\u0431\u0445\u0443\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u2014 \u0438 Portainer \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0442\u0435\u043a \u0441 \u043d\u043e\u0432\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code class=\"yaml\">name: Build and Deploy Project    on:     push:       branches:         - main    permissions:     packages: write     contents: read    jobs:     build-and-push:       runs-on: ubuntu-latest        steps:         - name: Checkout repository           uses: actions\/checkout@v4          - name: Set up Docker Buildx           uses: docker\/setup-buildx-action@v3          - name: Log in to GitHub Container Registry           uses: docker\/login-action@v3           with:             registry: ghcr.io             username: ${{ github.actor }}             password: ${{ secrets.GITHUB_TOKEN }}          - name: Build and push Docker image           uses: docker\/build-push-action@v6           with:             context: .             push: true             cache-from: type=registry,ref=ghcr.io\/prodreams\/tempproject:latest             cache-to: type=inline             tags: |               ghcr.io\/prodreams\/tempproject:latest                 ghcr.io\/prodreams\/tempproject:${{ github.sha }}      deploy:       runs-on: ubuntu-latest        needs: build-and-push        steps:         - name: Trigger Portainer webhook           env:             PORTAINER_WEBHOOK_URL: ${{ secrets.PORTAINER_WEBHOOK_URL }}           run: curl -fsS -m 30 -X POST \"$PORTAINER_WEBHOOK_URL\"<\/code><\/pre>\n<h4>\u0414\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u0431\u043e\u0442\u0430<\/h4>\n<p>\u0420\u0430\u043d\u0435\u0435 \u043c\u044b \u0443\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438 \u0431\u043e\u0442\u0430, \u0441\u043e\u0437\u0434\u0430\u0432 \u0441\u0442\u0435\u043a \u0432 Portainer.  <br \/> \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u043d\u043e\u0432\u044b\u0439 \u0434\u0435\u043f\u043b\u043e\u0439, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0431\u043e\u0442\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443.<\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"python\">import asyncio   import os    from aiogram import Dispatcher, Bot   from aiogram.filters import Command   from aiogram.types import Message   from dotenv import load_dotenv    load_dotenv()    async def send_message(message: Message) -&gt; None:       await message.answer(text=\"Hello World!\")    async def send_sticker(message: Message) -&gt; None:       await message.answer_sticker(sticker=\"CAACAgIAAxkBAAEKbW1lGVW1I6zFVLyovwo2rSgIt1l35QADJQACYp0ISWYMy8-mubjIMAQ\")    async def start():       bot = Bot(token=os.getenv('BOT_TOKEN'))       dp = Dispatcher()        dp.message.register(send_sticker, Command(commands=\"test\"))       dp.message.register(send_message)        try:           await dp.start_polling(bot)       finally:           await bot.session.close()     if __name__  \"__main__\":       asyncio.run(start())<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code><strong>send_sticker<\/strong><\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0442\u0438\u043a\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043c\u0430\u043d\u0434\u0430 <code><strong>\/test<\/strong><\/code> \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 <code>send_sticker<\/code>,<\/p>\n<\/li>\n<li>\n<p>\u043b\u044e\u0431\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 <code>send_message<\/code> \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <strong>\u00abHello World!\u00bb<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0431\u043e\u0442\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u043b\u0430\u0441\u044c: \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c <code>\/test<\/code> \u0438 \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432 \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0441\u0442\u0438\u043a\u0435\u0440.<\/p>\n<h4>\u041f\u0443\u0448 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439<\/h4>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0430\u0433 \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.  <br \/> \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e GitHub Actions \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0441\u0431\u043e\u0440\u043a\u0443 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043e\u0431\u0440\u0430\u0437\u0430 \u0438 \u0434\u0435\u043f\u043b\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 Portainer.<\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">git add .github\/workflows\/build_and_deploy.yaml docker-compose.yaml main.py  git commit -m \"CI\/CD: Deploy\"  git push<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0445\u043e\u0434\u0438\u043c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub \u0438 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b <strong>Actions<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fde\/dd0\/159\/fdedd01594ef637b0f202a6b2176d39d.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/fde\/dd0\/159\/fdedd01594ef637b0f202a6b2176d39d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fde\/dd0\/159\/fdedd01594ef637b0f202a6b2176d39d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0441\u044f Workflow, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0432 \u043d\u0451\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f <strong>\u0434\u0432\u0435 \u0437\u0430\u0434\u0430\u0447\u0438<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c51\/dc6\/667\/c51dc66678fcae62c87f63a25765120e.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c51\/dc6\/667\/c51dc66678fcae62c87f63a25765120e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c51\/dc6\/667\/c51dc66678fcae62c87f63a25765120e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 <strong>deploy<\/strong>, \u043c\u043e\u0436\u043d\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u043f\u0440\u043e\u0448\u043b\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e.  <br \/> \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u0430\u0434\u0440\u0435\u0441 \u0432\u0435\u0431\u0445\u0443\u043a\u0430 \u0432 \u043b\u043e\u0433\u0430\u0445 \u043d\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u2014 \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <strong>GitHub Secrets<\/strong>:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d1c\/3ee\/306\/d1c3ee3066c4646796506cd2543afc86.png\" width=\"1920\" height=\"1094\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d1c\/3ee\/306\/d1c3ee3066c4646796506cd2543afc86.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d1c\/3ee\/306\/d1c3ee3066c4646796506cd2543afc86.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0431\u043e\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c3d\/a36\/7bc\/c3da367bce651156362244222210b2f2.png\" width=\"1600\" height=\"2298\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c3d\/a36\/7bc\/c3da367bce651156362244222210b2f2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c3d\/a36\/7bc\/c3da367bce651156362244222210b2f2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0411\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e!<\/p>\n<p>CI\/CD-\u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0443\u0448\u0435 \u0432 <code>main<\/code> \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437,<\/p>\n<\/li>\n<li>\n<p>Portainer \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0442\u0435\u043a,<\/p>\n<\/li>\n<li>\n<p>\u0430 \u0432\u044b \u0441\u0440\u0430\u0437\u0443 \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0417\u0430 \u044d\u0442\u0438 \u0442\u0440\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0448\u0430\u0433 \u0437\u0430 \u0448\u0430\u0433\u043e\u043c \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u043a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0434\u0435\u043f\u043b\u043e\u044f:  <br \/> \u043e\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u2014 \u0434\u043e \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e CI\/CD.<\/p>\n<h4>\u0412 \u0447\u0451\u043c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e Portainer \u0441 Webhook<\/h4>\n<p>\u041e\u0431\u044b\u0447\u043d\u043e \u0434\u0435\u043f\u043b\u043e\u0439 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:  <br \/> Workflow \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u043e SSH \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0442\u0430\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430.  <br \/> \u042d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u043d\u043e \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043e\u043d \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u0439 \u0438 \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u0439.<\/p>\n<p>\u0421 Portainer \u0432\u0441\u0451 \u043f\u0440\u043e\u0449\u0435:<\/p>\n<ul>\n<li>\n<p>\u0447\u0435\u0440\u0435\u0437 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u0438\u043c\u0438,<\/p>\n<\/li>\n<li>\n<p>\u0430 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f Webhook \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0446\u0435\u043d\u0435\u043d \u0434\u043b\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u043e\u0432: \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c CI\/CD \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043d\u0430 \u043d\u0430\u0448 Telegram\u2011\u043a\u0430\u043d\u0430\u043b <a href=\"https:\/\/t.me\/press_any_button\" rel=\"noopener noreferrer nofollow\">\u00ab\u041a\u043e\u0434 \u043d\u0430 \u0441\u0430\u043b\u0444\u0435\u0442\u043a\u0435\u00bb<\/a> \u2014  <br \/> \u0442\u0430\u043c \u0432\u044b \u043d\u0430\u0439\u0434\u0451\u0442\u0435 \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u043a\u0430\u043a \u0434\u043b\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u043e\u0432, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u043e\u043f\u044b\u0442\u043d\u044b\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/934892\/\"> https:\/\/habr.com\/ru\/articles\/934892\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 Portainer \u0438 \u0441\u0444\u0435\u0440\u0430\u043c\u0438 \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u0434\u0432\u0443\u0445 \u043f\u0440\u043e\u0448\u043b\u044b\u0445 \u0441\u0442\u0430\u0442\u044c\u044f\u0445:<\/p>\n<ul>\n<li>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f: \u00ab<a href=\"https:\/\/habr.com\/ru\/articles\/917886\/\" rel=\"noopener noreferrer nofollow\">\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0434\u0435\u043f\u043b\u043e\u0439 \u0431\u043e\u0442\u0430 (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e) \u043d\u0430 Docker-\u0445\u043e\u0441\u0442\u0438\u043d\u0433\u0435 \u0441 Portainer<\/a>\u00bb<\/p>\n<\/li>\n<li>\n<p>\u0412\u0442\u043e\u0440\u0430\u044f: \u00ab<a href=\"https:\/\/habr.com\/ru\/articles\/924528\/\" rel=\"noopener noreferrer nofollow\">\u041e\u0434\u0438\u043d Portainer, \u0447\u0442\u043e\u0431 \u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435\u043c\u0438<\/a>\u00bb<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0434\u0435\u0441\u044c \u0432\u043f\u0435\u0440\u0432\u044b\u0435: <strong>Portainer<\/strong> \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u043f\u0430\u043d\u0435\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Docker (\u0438 Docker Swarm\/Kubernetes): \u0437\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441\u0435\u0442\u0438, \u0442\u043e\u043c\u0430 \u0438 \u043f\u0440\u0430\u0432\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u2014 \u0432\u0441\u0451 \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435.<\/p>\n<p>\u041c\u044b \u0443\u0436\u0435 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Portainer;<\/p>\n<\/li>\n<li>\n<p>\u0447\u0442\u043e \u0437\u0430 \u0441\u0435\u0440\u0432\u0438\u0441 <a href=\"http:\/\/DockerHosting.ru\" rel=\"noopener noreferrer nofollow\">DockerHosting.ru<\/a> \u0438 \u043a\u0430\u043a \u043e\u043d \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c <code>Dockerfile<\/code> \u0438 <code>docker-compose.yml<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u0437 Git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043a Portainer \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043d\u0438\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438 Docker.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c, <strong>\u043a\u0430\u043a \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c Portainer \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b CI\/CD \u0438 \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c Docker-\u043e\u0431\u0440\u0430\u0437\u044b<\/strong>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0437\u043d\u0430\u0435\u043c, <strong>\u043a\u0430\u043a \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c Portainer Business Edition<\/strong>.<\/p>\n<blockquote>\n<p>\u041a\u043e\u0440\u043e\u0442\u043a\u043e \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u0441\u044f \u0441 \u0442\u0435\u043c\u043e\u0439:  <br \/>   <strong>CI<\/strong> (Continuous Integration) \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0434\u0430 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438.  <br \/>   <strong>CD<\/strong> (Continuous Delivery\/Deployment) \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0430\/\u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.  <br \/>   <strong>\u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 (registry)<\/strong> \u2014 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432 (\u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0435 \u0438\u043b\u0438 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0435), \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e Portainer \u0438 \u0432\u0430\u0448\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u043e\u0431\u0440\u0430\u0437\u044b \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f.<\/p>\n<\/blockquote>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043a \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u044e \u00ab<a href=\"https:\/\/pressanybutton.ru\/post\/devops\/cicd-osnovy-napisaniya-workflow\/\" rel=\"noopener noreferrer nofollow\">CI\/CD: \u043e\u0441\u043d\u043e\u0432\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f Workflow<\/a>\u00bb, \u0447\u0442\u043e\u0431\u044b \u0433\u043b\u0443\u0431\u0436\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u0438\u044f CI\/CD \u0438 Workflow.<\/p>\n<hr\/>\n<h3>\u0413\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c Docker-\u043e\u0431\u0440\u0430\u0437\u044b<\/h3>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449 (Docker Registry). <code>Dockerfile<\/code> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442, <strong>\u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437<\/strong>, \u0430 \u0437\u0430\u043f\u0438\u0441\u044c <code>build: .<\/code> \u0432 <code>docker-compose.yml<\/code> \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u0435\u0433\u043e <strong>\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e<\/strong>.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: <strong>\u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0435\u0441\u0442\u0440<\/strong>. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u0434\u0435\u043f\u043b\u043e\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 <code>docker pull<\/code> \u0438 \u0437\u0430\u0431\u0435\u0440\u0451\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f CI\/CD: \u0432\u0441\u044f \u0442\u044f\u0436\u0451\u043b\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0435, \u0430 \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0435 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430.<\/p>\n<h4>\u041a\u0430\u043a\u0438\u0435 \u0431\u044b\u0432\u0430\u044e\u0442 \u0440\u0435\u0435\u0441\u0442\u0440\u044b<\/h4>\n<ul>\n<li>\n<p><strong>Docker Hub<\/strong> \u2014 \u0441\u0430\u043c\u043e\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>Self-hosted<\/strong> \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <strong>Harbor<\/strong> \u2014 \u0440\u0435\u0435\u0441\u0442\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0435 \u043d\u0430 \u0441\u0432\u043e\u0451\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u0435\u0441\u0442\u0440\u044b \u0443 git-\u0445\u043e\u0441\u0442\u0438\u043d\u0433\u043e\u0432<\/strong>: <strong>GitHub Container Registry (<\/strong><a href=\"http:\/\/ghcr.io\" rel=\"noopener noreferrer nofollow\"><strong>ghcr.io<\/strong><\/a><strong>)<\/strong>, <strong>GitLab Container Registry<\/strong>, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 <strong>Gitea<\/strong> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0427\u0435\u043c \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f<\/h4>\n<ul>\n<li>\n<p><strong>Docker Hub<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043b\u044e\u0441\u044b: \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0447\u0430\u0442\u044c, \u043c\u043d\u043e\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0431\u0440\u0430\u0437\u043e\u0432.  <\/p>\n<\/li>\n<li>\n<p>\u041c\u0438\u043d\u0443\u0441\u044b: \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0445 \u043f\u043b\u0430\u043d\u0430\u0445 (\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0438 \u043e\u0431\u044a\u0451\u043c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f), \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Self-hosted (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Harbor)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043b\u044e\u0441\u044b: \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u044c, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0438\u043d\u0443\u0441\u044b: \u043d\u0443\u0436\u043d\u043e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Git-\u0445\u043e\u0441\u0442\u0438\u043d\u0433\u0438 (GHCR\/GitLab \u0438 \u0434\u0440.)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043b\u044e\u0441\u044b: \u043e\u0431\u0440\u0430\u0437\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0440\u044f\u0434\u043e\u043c \u0441 \u043a\u043e\u0434\u043e\u043c, \u0443\u0434\u043e\u0431\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f, \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 CI\/CD.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0438\u043d\u0443\u0441\u044b: \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u0438 \u0435\u0451 \u043b\u0438\u043c\u0438\u0442\u0430\u043c.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h4>\u041a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/h4>\n<ol>\n<li>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0437 \u0438\u0437 <code>Dockerfile<\/code> \u2014 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438\u043b\u0438 \u0432 CI\/CD.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0435 \u0442\u0435\u0433:<\/p>\n<ul>\n<li>\n<p><strong>\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439<\/strong> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0435\u0440\u0441\u0438\u044f <code>1.2.3<\/code> \u0438\u043b\u0438 SHA \u043a\u043e\u043c\u043c\u0438\u0442\u0430),<\/p>\n<\/li>\n<li>\n<p><strong>\u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0438\u0439<\/strong> (<code>latest<\/code>).   \u0425\u043e\u0440\u043e\u0448\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>\u043e\u0431\u0430 \u0442\u0435\u0433\u0430<\/strong>: \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u043e\u0441\u0442\u0438 \u0438 <code>latest<\/code> \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0435 \u043e\u0431\u0440\u0430\u0437 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 (<code>docker push<\/code> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043a\u0430\u043a <code>git push<\/code>, \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437).<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 <code>docker-compose.yml<\/code> \u0438 \u0432\u043c\u0435\u0441\u0442\u043e <code>build: .<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0435 <code>image:<\/code>.   \u0414\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>\u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0435\u0433<\/strong> \u0438\u043b\u0438 <strong>\u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442<\/strong> (<code>@sha256:\u2026<\/code>), \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e <code>latest<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u042f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0441\u0432\u043e\u0439 git-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u0431\u0430\u0437\u0435 <strong>Gitea<\/strong> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043a\u043e\u0434\u0430, \u0438 Docker-\u043e\u0431\u0440\u0430\u0437\u043e\u0432. \u041d\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0440\u0435\u0435\u0441\u0442\u0440\u043e\u043c \u043e\u0442 GitHub \u2014 <strong>GHCR (<\/strong><a href=\"http:\/\/ghcr.io\" rel=\"noopener noreferrer nofollow\"><strong>ghcr.io<\/strong><\/a><strong>)<\/strong>.  <br \/> \u0415\u0441\u043b\u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u0440\u043e self-hosted-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u2014 \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0438 \u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u044e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.<\/p>\n<hr\/>\n<h3>\u041f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 GitHub: <a href=\"https:\/\/github.com\/proDreams\/tempProject\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/proDreams\/tempProject<\/a>.<\/p>\n<p>\u042d\u0442\u043e Telegram-\u0431\u043e\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u043b\u044e\u0431\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u043c <strong>\u00abHello World!\u00bb<\/strong>.  <br \/> \u041e\u043d \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u0448\u0430\u0433\u0438 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0430 \u0432\u044b \u043f\u043e\u0442\u043e\u043c \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u043e\u0434 \u0441\u0432\u043e\u0439.<\/p>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c, \u0447\u0442\u043e \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438.<\/p>\n<h4>Dockerfile<\/h4>\n<p><code>Dockerfile<\/code> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code>FROM python:3.13-slim    WORKDIR \/code    COPY requirements.txt \/code    RUN pip install --upgrade pip &amp;&amp; pip install -r requirements.txt    COPY . \/code    CMD [ \"python\", \".\/main.py\" ]<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0448\u0430\u0433 \u0437\u0430 \u0448\u0430\u0433\u043e\u043c:<\/p>\n<ol>\n<li>\n<p><code><strong>FROM python:3.13-slim<\/strong><\/code>   \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 \u0441 Python 3.13 \u043d\u0430 \u043e\u0431\u043b\u0435\u0433\u0447\u0451\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 (<code>slim<\/code>). \u0422\u0430\u043a\u043e\u0439 \u043e\u0431\u0440\u0430\u0437 \u0432\u0435\u0441\u0438\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p><code><strong>WORKDIR \/code<\/strong><\/code>   \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430. \u0412\u0441\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0438\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p><code><strong>COPY requirements.txt \/code<\/strong><\/code>   \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u042d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0448\u0430\u0433\u043e\u043c, \u0447\u0442\u043e\u0431\u044b Docker \u043c\u043e\u0433 \u0437\u0430\u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u0438 \u043d\u0435 \u0441\u0442\u0430\u0432\u0438\u043b \u0438\u0445 \u0437\u0430\u043d\u043e\u0432\u043e \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p><code><strong>RUN pip install --upgrade pip &amp;&amp; pip install -r requirements.txt<\/strong><\/code>   \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c <code>pip<\/code> \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0437 <code>requirements.txt<\/code>.   \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0448\u0430\u0433\u0443, \u0435\u0441\u043b\u0438 <code>requirements.txt<\/code> \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f, \u044d\u0442\u043e\u0442 \u044d\u0442\u0430\u043f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d (Docker \u0432\u043e\u0437\u044c\u043c\u0451\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043a\u0435\u0448\u0430).<\/p>\n<\/li>\n<li>\n<p><code><strong>COPY . \/code<\/strong><\/code>   \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p><code><strong>CMD [\"python\", \".\/<\/strong><\/code><a href=\"http:\/\/main.py\" rel=\"noopener noreferrer nofollow\"><code><strong>main.py<\/strong><\/code><\/a><code><strong>\"]<\/strong><\/code>   \u0417\u0430\u0434\u0430\u0451\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u2014 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430\u0448\u0435\u0433\u043e Telegram-\u0431\u043e\u0442\u0430.   \u0412\u0430\u0436\u043d\u043e: <code>CMD<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 (<code>docker run ...<\/code>), \u0430 \u0432\u043e\u0442 <code>ENTRYPOINT<\/code> \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u042d\u0442\u043e\u0442 <code>Dockerfile<\/code> \u0443\u0436\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.<\/p>\n<h4>docker-compose.yaml<\/h4>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u0444\u0430\u0439\u043b <code>docker-compose.yaml<\/code> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"yaml\">services:     test-bot:       build: .       container_name: test-bot       environment:         - BOT_TOKEN=${BOT_TOKEN}<\/code><\/pre>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0451\u043c, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441 <code><strong>test-bot<\/strong><\/code>, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e Docker <strong>\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0437 \u0438\u0437 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u0430\u043f\u043a\u0438<\/strong> (<code>build: .<\/code>) \u043f\u043e <code>Dockerfile<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u0438\u043c\u044f <code><strong>test-bot<\/strong><\/code>. \u042d\u0442\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u043f\u043e\u0438\u0441\u043a \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u043b\u043e\u0433\u043e\u0432 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code><strong>BOT_TOKEN<\/strong><\/code>.   \u0415\u0451 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0431\u0435\u0440\u0451\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u043b\u0438\u0431\u043e \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0445\u043e\u0441\u0442\u0435,<\/p>\n<\/li>\n<li>\n<p>\u043b\u0438\u0431\u043e \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 <code><strong>.env<\/strong><\/code>, \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0440\u044f\u0434\u043e\u043c \u0441 <code>docker-compose.yaml<\/code>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<blockquote>\n<p>\u0421\u043e\u0432\u0435\u0442: \u0444\u0430\u0439\u043b <code>.env<\/code> \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u0439.  <br \/>   \u0412 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0435\u0433\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442, \u0430 \u0434\u0435\u043b\u0430\u044e\u0442 <code>.env.example<\/code> \u0441 \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438, \u0447\u0442\u043e\u0431\u044b \u0434\u0440\u0443\u0433\u0438\u043c \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u0430\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043d\u0443\u0436\u043d\u044b.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0437\u0436\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c CI\/CD, \u0441\u0442\u0440\u043e\u0447\u043a\u0443 <code>build: .<\/code> \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043d\u0430 <code><strong>image: ...<\/strong><\/code>, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 \u043e\u0431\u0440\u0430\u0437.<\/p>\n<h4>main.py<\/h4>\n<p>\u041a\u043e\u0434 \u0431\u043e\u0442\u0430:<\/p>\n<pre><code class=\"python\">import asyncio   import os    from aiogram import Dispatcher, Bot   from aiogram.types import Message   from dotenv import load_dotenv    load_dotenv()    async def send_message(message: Message) -&gt; None:       await message.answer(text=\"Hello World!\")    async def start() -&gt; None:       bot = Bot(token=os.getenv('BOT_TOKEN'))       dp = Dispatcher()        dp.message.register(send_message)        try:           await dp.start_polling(bot)       finally:           await bot.session.close()     if __name__  \"__main__\":       asyncio.run(start())<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442:<\/p>\n<ul>\n<li>\n<p><code><strong>load_dotenv()<\/strong><\/code>   \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 <code>.env<\/code>.   \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. \u0412 Docker Compose \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u0437 \u0441\u0435\u043a\u0446\u0438\u0438 <code>environment<\/code> \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 <code>env_file<\/code>.   \u0422\u043e \u0435\u0441\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u044d\u0442\u043e\u0442 \u0432\u044b\u0437\u043e\u0432 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u0435\u043d, \u043d\u043e \u0438 \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/strong>   \u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>send_message<\/code> \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u043b\u044e\u0431\u043e\u0435 \u0432\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0444\u0440\u0430\u0437\u043e\u0439 <strong>\u00abHello World!\u00bb<\/strong>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <\/strong><code><strong>start()<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 <code>Bot<\/code> \u0441 \u0442\u043e\u043a\u0435\u043d\u043e\u043c \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>BOT_TOKEN<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 <code>Dispatcher<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f <strong>\u0432\u0441\u0435\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/strong> (<code>dp.message.register(send_message)<\/code>).<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0417\u0430\u043f\u0443\u0441\u043a long polling<\/strong>   <code>dp.start_polling(bot)<\/code> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c long polling \u2014 \u0431\u043e\u0442 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u043e\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u044b Telegram \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b<\/strong>   \u0412 \u0431\u043b\u043e\u043a\u0435 <code>finally<\/code> \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f HTTP-\u0441\u0435\u0441\u0441\u0438\u044f \u0431\u043e\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u00ab\u0432\u0438\u0441\u044f\u0447\u0438\u0445\u00bb \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0417\u0430\u043f\u0443\u0441\u043a \u0438\u0437 \u0444\u0430\u0439\u043b\u0430<\/strong>   <code>if <strong>name<\/strong>  \"__main__\": <\/code><a href=\"http:\/\/asyncio.run\" rel=\"noopener noreferrer nofollow\"><code>asyncio.run<\/code><\/a><code>(start())<\/code> \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u0431\u043e\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0430 \u043d\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0435 \u0435\u0433\u043e \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u043e\u0434\u0443\u043b\u044c.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>Workflow \u0441\u0431\u043e\u0440\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u0430<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435. \u041d\u0430\u0448\u0430 \u0446\u0435\u043b\u044c \u2014 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Workflow, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 <strong>\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c Docker-\u043e\u0431\u0440\u0430\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0435\u0441\u0442\u0440 GitHub<\/strong>.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f <strong>GitHub Actions<\/strong> \u2014 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0432 GitHub \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u0434\u043b\u044f CI\/CD. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0443\u0448\u0435 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 (\u0438\u043b\u0438 \u043f\u043e \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u043c).<\/p>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ul>\n<li>\n<p>\u0412 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code><strong>.github<\/strong><\/code> \u2014 \u0437\u0434\u0435\u0441\u044c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432\u0441\u0451, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 GitHub.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u0451 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0430\u043f\u043a\u0443 <code><strong>workflows<\/strong><\/code> \u2014 \u0438\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c GitHub Actions \u0438\u0449\u0435\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0444\u0430\u0439\u043b <code><strong>build_and_deploy.yaml<\/strong><\/code>.   \u0412 \u043d\u0451\u043c \u043c\u044b \u043e\u043f\u0438\u0448\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u043e \u0441\u0431\u043e\u0440\u043a\u0435 \u0438 \u0434\u0435\u043f\u043b\u043e\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0431\u043e\u0440\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<h4>build_and_deploy.yaml<\/h4>\n<p>\u0424\u0430\u0439\u043b Workflow \u0446\u0435\u043b\u0438\u043a\u043e\u043c:<\/p>\n<pre><code class=\"yaml\">name: Build and Deploy Project    on:     push:       branches:         - main    permissions:     packages: write     contents: read    jobs:     build-and-push:       runs-on: ubuntu-latest        steps:         - name: Checkout repository           uses: actions\/checkout@v4          - name: Set up Docker Buildx           uses: docker\/setup-buildx-action@v3          - name: Log in to GitHub Container Registry           uses: docker\/login-action@v3           with:             registry: ghcr.io             username: ${{ github.actor }}             password: ${{ secrets.GITHUB_TOKEN }}          - name: Build and push Docker image           uses: docker\/build-push-action@v6           with:             context: .             push: true             cache-from: type=registry,ref=ghcr.io\/prodreams\/tempproject:latest             cache-to: type=inline             tags: |               ghcr.io\/prodreams\/tempproject:latest                 ghcr.io\/prodreams\/tempproject:${{ github.sha }}<\/code><\/pre>\n<h4>\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/h4>\n<ul>\n<li>\n<p><code><strong>name<\/strong><\/code>   \u041f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 Workflow. \u041e\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435 <strong>Actions<\/strong> \u043d\u0430 GitHub.<\/p>\n<\/li>\n<li>\n<p><code><strong>on.push.branches: main<\/strong><\/code>   \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Workflow \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u0443\u0448\u0435 \u0432 \u0432\u0435\u0442\u043a\u0443 <strong>main<\/strong>. \u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u0435\u0442\u043a\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\u0430, \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u0435 <code>main<\/code> \u043d\u0430 \u043d\u0443\u0436\u043d\u0443\u044e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>production<\/code>).<\/p>\n<\/li>\n<li>\n<p><code><strong>permissions<\/strong><\/code>   \u0414\u0430\u0451\u043c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c\u0443 <code>GITHUB_TOKEN<\/code> \u043f\u0440\u0430\u0432\u0430:<\/p>\n<ul>\n<li>\n<p><code>packages: write<\/code> \u2014 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u044b \u0432 GitHub Container Registry,<\/p>\n<\/li>\n<li>\n<p><code>contents: read<\/code> \u2014 \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u0434 \u0438\u0437 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><code><strong>runs-on: ubuntu-latest<\/strong><\/code>   GitHub \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0431\u043e\u0440\u043a\u0443 \u043d\u0430 Linux-\u0440\u0430\u043d\u043d\u0435\u0440\u0435 (\u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 Ubuntu).<\/p>\n<\/li>\n<li>\n<p><strong>Checkout<\/strong>   \u0417\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043e\u0434<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-469913","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/469913","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=469913"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/469913\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=469913"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=469913"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=469913"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}