{"id":359234,"date":"2024-05-21T00:28:24","date_gmt":"2024-05-21T00:28:24","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=359234"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=359234","title":{"rendered":"<span>\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0435\u043d\u0434\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u043b\u044f \u0441\u0430\u043c\u044b\u0445 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 + \u0431\u044d\u043a\u0435\u043d\u0434)<\/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<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/211\/307\/f9c\/211307f9c627e6618b0cbf560db34211.png\" width=\"1878\" height=\"1080\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/211\/307\/f9c\/211307f9c627e6618b0cbf560db34211.png\"\/><\/figure>\n<p>\u0412\u043d\u043e\u0441\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0442\u0443\u0442 \u0436\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0437\u0430\u0434\u0435\u043f\u043b\u043e\u0435\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0441\u0442\u0440\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e, \u2014 \u043c\u0435\u0447\u0442\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c \u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u043c: \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u043c \u0434\u0432\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430 \u043d\u0430 \u0431\u0430\u0437\u0435 minikube \u0438\u043b\u0438 Docker \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043a\u043e\u043c\u043c\u0438\u0447\u0435\u043d\u044b\u0445 \u0432 Git. \u0411\u044d\u043a\u0435\u043d\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0430 Go, \u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u2014 \u043d\u0430 Vue.js. \u0412\u0441\u0435 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u044f\u043c\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0447\u0442\u043e, \u043d\u0435\u0441\u043e\u043c\u043d\u0435\u043d\u043d\u043e, \u043f\u043e\u0432\u044b\u0441\u0438\u0442 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u041d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u0430 werf (\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/ru.werf.io\/documentation\/v1.2\/\"><u>\u043d\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0430\u0439\u0442\u0435<\/u><\/a>) \u2014 \u0441 \u0435\u0435 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0434\u0435\u043f\u043b\u043e\u0439 \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.  \u0412\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435.\u00a0<\/p>\n<blockquote>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/759040\/\"><u>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/u><\/a> \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b <a href=\"https:\/\/deckhouse.ru\/\">Deckhouse<\/a> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u044b <a href=\"https:\/\/ru.werf.io\/\">werf<\/a>. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430 \u043c\u044b \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e werf \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u0412\u0430\u043c \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043c\u044b \u0432\u0441\u0451 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u044b\u043b\u0430 \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0439.<\/p>\n<\/blockquote>\n<h2>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e <a href=\"https:\/\/github.com\/flant\/examples\/tree\/master\/2023\/08-deckhouse-werf\"><u>\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/u><\/a> \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041f\u043e\u043a\u0430 \u043e\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0439 \u0431\u044d\u043a\u0435\u043d\u0434 \u043d\u0430 Go \u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 Kubernetes Helm-\u0447\u0430\u0440\u0442\u0430\u043c\u0438. \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043a\u0430\u043a \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u0438\u0445 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c \u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0442 \u0436\u0435\u0441\u0442\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434 \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0440\u0430\u0437\u0431\u0438\u0432 \u0435\u0433\u043e \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430: \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432\u0435\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u0430 \u0432 \u0431\u044d\u043a\u0435\u043d\u0434\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043d\u0430 REST-\u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0447\u0430\u0440\u0442\u044b \u0434\u043b\u044f \u043d\u043e\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Docker Compose \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0431\u043e\u043b\u0435\u0435 \u00ab\u0441\u043b\u043e\u0436\u043d\u044b\u043c\u00bb \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u2014 \u0432\u0435\u0434\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0438 \u0431\u044d\u043a\u0435\u043d\u0434 \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u0438\u043c\u0435\u043d\u0438. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u043e\u0439 \u043a \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0436\u0438\u0437\u043d\u0438.\u00a0<\/p>\n<h3>\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <a href=\"https:\/\/github.com\/flant\/examples\/tree\/master\/2023\/08-deckhouse-werf\"><u>\u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/u><\/a> \u0432 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>backend<\/code> \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 \u043d\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0411\u0414 \u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e REST\u00a0API.\u00a0<\/p>\n<p>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0441\u044f \u0432 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>frontend<\/code> \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430, \u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u043a\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e: \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u043d\u0430 \u0441\u0442\u0430\u0434\u0438\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Vue.js.\u00a0<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:<\/p>\n<pre><code class=\"bash\">$ tree -a . . \u2514\u2500\u2500 backend    \u251c\u2500\u2500 .helm    \u2502   \u2514\u2500\u2500 templates    \u2502       \u251c\u2500\u2500 database.yaml    \u2502       \u251c\u2500\u2500 deployment.yaml    \u2502       \u251c\u2500\u2500 ingress.yaml    \u2502       \u251c\u2500\u2500 job-db-setup-and-migrate.yaml    \u2502       \u2514\u2500\u2500 service.yaml    \u251c\u2500\u2500 Dockerfile    \u251c\u2500\u2500 cmd    \u2502   \u2514\u2500\u2500 main.go    \u251c\u2500\u2500 db    \u2502   \u2514\u2500\u2500 migrations    \u2502       \u251c\u2500\u2500 000001_create_talkers_table.down.sql    \u2502       \u2514\u2500\u2500 000001_create_talkers_table.up.sql    \u251c\u2500\u2500 go.mod    \u251c\u2500\u2500 go.sum    \u251c\u2500\u2500 internal    \u2502   \u251c\u2500\u2500 app    \u2502   \u2502   \u2514\u2500\u2500 app.go    \u2502   \u251c\u2500\u2500 common    \u2502   \u2502   \u2514\u2500\u2500 json_logger_filter.go    \u2502   \u251c\u2500\u2500 controllers    \u2502   \u2502   \u2514\u2500\u2500 db_controllers.go    \u2502   \u2514\u2500\u2500 services    \u2502       \u2514\u2500\u2500 db_service.go    \u251c\u2500\u2500 templates    \u2502   \u251c\u2500\u2500 index.html    \u2502   \u251c\u2500\u2500 remember.html    \u2502   \u2514\u2500\u2500 say.html    \u2514\u2500\u2500 werf.yaml <\/code><\/pre>\n<h3>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0412 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430 \u0432\u0435\u0431-\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 Vue.js, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0432\u0441\u0435, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432, \u0430 \u043e\u0442\u0432\u0435\u0442\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435 \u0432 HTML, \u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON \u2014 \u043a\u0430\u043a \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \ud83d\ude42<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0434\u0430\u043b\u0438\u043c \u0432 \u0444\u0430\u0439\u043b\u0435 <code>internal\/app\/app.go<\/code> \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/<\/code>, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430 \u043d\u0435\u0433\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434. \u041a \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u043e\u0442\u0430\u043c <code>remember<\/code> \u0438 <code>say<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438\u0437 \u0411\u0414, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0434\u043f\u0443\u0442\u044c <code>\/api<\/code> (\u0434\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a: <code>remember\/api<\/code>, <code>say\/api<\/code>), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e \u043d\u0443\u0436\u043d\u044b\u043c \u043f\u0443\u0442\u044f\u043c \u043f\u0440\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u0438 Docker Compose \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"go\">func Run() { route := gin.New() route.Use(gin.Recovery()) route.Use(common.JsonLogger())   route.GET(\"\/api\/remember\", controllers.RememberController) route.GET(\"\/api\/say\", controllers.SayController)   err := route.Run() if err != nil { return } }<\/code><\/pre>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong><\/p>\n<p>\u041b\u0443\u0447\u0448\u0435 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u0442\u044c, \u043a\u0430\u043a \u0431\u0443\u0434\u0443\u0442 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0430\u044f \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u0440\u0430\u0437\u0443 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c API. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043c\u0430\u0436\u043e\u0440\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435 \u043d\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b API \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u043e \u043f\u0443\u0442\u0438 \/api\/v2, \u0430 \u0441\u0442\u0430\u0440\u044b\u0435 \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u043d\u0430 \/api\/v1.<\/p>\n<\/blockquote>\n<p>\u0417\u0430\u043c\u0435\u043d\u0438\u043c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445 \u0442\u0438\u043f \u043e\u0442\u0432\u0435\u0442\u0430 \u0441 HTML \u043d\u0430 JSON, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>internal\/controllers\/db_controllers.go<\/code>:<\/p>\n<pre><code class=\"go\">func RememberController(c *gin.Context) { dbType, dbPath := services.GetDBCredentials()   db, err := sql.Open(dbType, dbPath) if err != nil { panic(err) }   message := c.Query(\"message\") name := c.Query(\"name\")   _, err = db.Exec(\"INSERT INTO talkers (message, name) VALUES (?, ?)\", message, name) if err != nil { panic(err) }   c.JSON(http.StatusOK, gin.H{ \"Name\":    name, \"Message\": message, })   defer db.Close() }<\/code><\/pre>\n<p>\u0412 \u043d\u0435\u043c \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043a\u0430\u043a \u043f\u0440\u0435\u0436\u0434\u0435: \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0444\u043e\u0440\u043c\u044b \u043d\u0430 \u0441\u0430\u0439\u0442\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0443, \u0438 \u0438\u0445 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0432 \u0411\u0414. \u0418\u0437\u043c\u0435\u043d\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0432\u0435\u0442 \u0441 \u0432\u044b\u0437\u043e\u0432\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 HTML \u043d\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e JSON (\u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430, \u0435\u0441\u043b\u0438 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u043d\u0438\u0437\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 <code>c.JSON<\/code>).<\/p>\n<p>\u041a\u043e\u0434 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0411\u0414 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u0432 \u0442\u043e\u043c \u0436\u0435 \u0444\u0430\u0439\u043b\u0435 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">func SayController(c *gin.Context) { dbType, dbPath := services.GetDBCredentials()   db, err := sql.Open(dbType, dbPath) if err != nil { panic(err) }   result, err := db.Query(\"SELECT * FROM talkers\") if err != nil { panic(err) }   count := 0 var data []map[string]string   for result.Next() { count++ var id int var message string var name string   err = result.Scan(&amp;id, &amp;message, &amp;name) if err != nil { panic(err) }   data = append(data, map[string]string{ \"Name\":    name, \"Message\": message}) } if count == 0 { c.JSON(http.StatusOK, gin.H{ \"Error\": \"There are no messages from talkers!\", }) } else { c.JSON(http.StatusOK, gin.H{ \"Messages\": data, }) } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0441\u0435 \u0442\u0430\u043a\u0436\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u2014 \u043c\u044b \u043b\u0438\u0448\u044c \u0437\u0430\u043c\u0435\u043d\u0438\u043b\u0438 HTML \u043d\u0430 JSON (\u0434\u0432\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0431\u043b\u043e\u043a\u0430 \u043a\u043e\u0434\u0430, \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0441 <code>c.JSON<\/code>).<\/p>\n<p>\u0423\u0440\u0430! \u041e\u0442\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0435\u0440\u0435\u0439\u0434\u044f \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>backend<\/code> \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435:<\/p>\n<pre><code class=\"bash\">werf converge --repo &lt;\u0418\u041c\u042f \u041f\u041e\u041b\u042c\u0417\u041e\u0412\u0410\u0422\u0415\u041b\u042f DOCKER HUB>\/habr-app<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0443 \/<code>say<\/code> \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0411\u0414 \u0432 \u0432\u0438\u0434\u0435 JSON-\u0444\u0430\u0439\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">$ curl https:\/\/habrapp.example.com\/say | jq  {   \"Messages\": [     {       \"Message\": \"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!\",       \"Name\": \"Zhbert\"     }   ] }<\/code><\/pre>\n<blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0441 \u044d\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430, \u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u2014 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u0432\u0435\u0440\u043d\u0435\u0442\u0441\u044f JSON, \u043d\u043e \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0443\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u044d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u043d\u0435 \u043f\u0443\u0433\u0430\u0439\u0442\u0435\u0441\u044c.<\/p>\n<\/blockquote>\n<p>\u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0443\u0434\u0430\u043b\u0438\u043b\u0438 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 <code>\/<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f 404-\u044f \u043e\u0448\u0438\u0431\u043a\u0430, \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435:<\/p>\n<pre><code class=\"bash\">$ curl https:\/\/habrapp.example.com  404 page not found<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043c\u044b \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c, \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 <code>backend<\/code> \u0444\u0430\u0439\u043b <code>werf.yaml<\/code> \u043d\u0430 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0432\u044b\u0448\u0435 \u2014 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u0441\u0440\u0430\u0437\u0443 \u0434\u0432\u0443\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0433\u043e.<\/p>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0436, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430.<\/p>\n<h3>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Vue.js, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430: \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0431\u044d\u043a\u0435\u043d\u0434\u0430.<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 <a href=\"https:\/\/cli.vuejs.org\/ru\/guide\/creating-a-project.html\"><u>Vue CLI<\/u><\/a> \u043d\u0430 \u0432\u0430\u0448\u0443 \u043c\u0430\u0448\u0438\u043d\u0443. \u041b\u0443\u0447\u0448\u0435 \u0441\u0440\u0430\u0437\u0443 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/docs.npmjs.com\/about-npm\"><u>npm<\/u><\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043e\u043d \u043d\u0430\u043c \u0435\u0449\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u043e\u0435 Vue-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">vue create frontend<\/code><\/pre>\n<blockquote>\n<p>\u0422\u0430\u043a\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <a href=\"https:\/\/cli.vuejs.org\/ru\/guide\/creating-a-project.html\">\u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c<\/a>, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/vuejs\/create-vue\">create-vue<\/a> \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u0430\u0440\u043a\u0430\u0441\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<\/blockquote>\n<p>\u0412 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p>\n<pre><code class=\"bash\">> Default ([Vue 3] babel, eslint<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0437\u0430\u0439\u043c\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u044f\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0443\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"bash\">Vue CLI v5.0.8 \u2728  Creating project in \/Users\/zhbert\/Programming\/habr-werf-local-stend\/frontend. \u2699\ufe0f  Installing CLI plugins. This might take a while...  added 862 packages, and audited 863 packages in 24s  packages are looking for funding   run `npm fund` for details  found 0 vulnerabilities ?  Invoking generators... ?  Installing additional dependencies...  added 101 packages, and audited 964 packages in 3s  packages are looking for funding   run `npm fund` for details  found 0 vulnerabilities \u2693  Running completion hooks...  ?  Generating README.md...  ?  Successfully created project frontend. ?  Get started with the following commands:   $ cd frontend  $ npm run serve<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u043c\u0443 \u0441\u043e\u0432\u0435\u0442\u0443 \u0432 \u0441\u0430\u043c\u043e\u043c \u043a\u043e\u043d\u0446\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"bash\">npm run serve  > frontend@0.1.0 serve > vue-cli-service serve   INFO  Starting development server...    DONE  Compiled successfully in 1699ms                                                                                                                                                                                                       14:48:03    App running at:   - Local:   http:\/\/localhost:8080\/   - Network: http:\/\/192.168.1.100:8080\/    Note that the development build is not optimized.   To create a production build, run npm run build.<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043f\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/279\/4ce\/7f3\/2794ce7f391bd7480e3341009d4fa8da.png\" width=\"1600\" height=\"781\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/279\/4ce\/7f3\/2794ce7f391bd7480e3341009d4fa8da.png\"\/><\/figure>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0422\u0435\u043f\u0435\u0440\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0435\u0433\u043e \u043f\u043e\u0434 \u043d\u0430\u0448\u0438 \u043d\u0443\u0436\u0434\u044b \u2014 \u0443\u0434\u0430\u043b\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u0432\u0441\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043a \u0411\u0414: \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0444\u043e\u0440\u043c\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u0438\u0445 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c <a href=\"https:\/\/getbootstrap.com\/\"><u>Bootsrtap<\/u><\/a>, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u043d\u0435 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e CDN, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u043c\u0430\u0448\u0438\u043d\u0435:<\/p>\n<pre><code class=\"bash\">$ npm i bootstrap@5.3.1  added 2 packages, and audited 966 packages in 4s  Packages are looking for funding   run `npm fund` for details  found 0 vulnerabilities<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 CSS-\u0441\u0442\u0438\u043b\u0435\u0439, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u0435\u0440\u0441\u0442\u043a\u0438 \u0441\u0430\u0439\u0442\u043e\u0432 \u043b\u044e\u0431\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438: \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443, \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043a\u043d\u043e\u043f\u043a\u0438, \u0447\u0435\u043a\u0431\u043e\u043a\u0441\u044b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c Bootstrap \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0438\u043c\u043f\u043e\u0440\u0442 \u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 <code>src\/App.vue<\/code>:<\/p>\n<pre><code class=\"javascript\">&lt;style> @import \"bootstrap\"; &lt;\/style><\/code><\/pre>\n<p>Vue\u00a0CLI \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0434\u0432\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430: \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 <em>App<\/em> \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 <em>HelloWorld<\/em>, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e. \u041e\u043d\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0444\u0430\u0439\u043b\u0430\u043c\u0438 <code>*.vue<\/code> \u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>src\/components<\/code>. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 <em>HelloWorld<\/em> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0439 \u043d\u0430\u043c HTML-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430, \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u044e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443\u0431\u0435\u0440\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0437\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 <em>HelloWorld<\/em>. \u0412 \u0438\u0442\u043e\u0433\u0435 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (<code>frontend\/src\/App.vue<\/code>) \u0443 \u043d\u0430\u0441 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">&lt;template>   &lt;HelloWorld\/> &lt;\/template>  &lt;script> import HelloWorld from '.\/components\/HelloWorld.vue'   export default {   name: 'App',   components: {     HelloWorld   } } &lt;\/script>  &lt;style> @import \"bootstrap\"; &lt;\/style><\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0442\u0440\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0430: <code>template<\/code>, <code>script<\/code> \u0438 <code>style<\/code>. \u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f HTML-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u2014 JS-\u0447\u0430\u0441\u0442\u044c, \u0430 \u0432 \u0442\u0440\u0435\u0442\u044c\u0435\u043c \u2014 \u0441\u0442\u0438\u043b\u0438 CSS, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435. \u041f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Vue \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0432\u0441\u0435 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 <code>index.html<\/code> \u0438\u0437 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <code>components\/HelloWorld.vue<\/code>, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0435\u0433\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b <code>template<\/code>:<\/p>\n<pre><code class=\"xml\">&lt;template>   &lt;div class=\"container mt-5\">     &lt;form class=\"row g-3\" action=\"\/api\/remember\">       &lt;div class=\"col-auto\">         &lt;div class=\"input-group mb-3\">           &lt;span class=\"input-group-text\" id=\"name\">Name&lt;\/span>           &lt;input type=\"text\" class=\"form-control\" placeholder=\"Name\" name=\"name\">         &lt;\/div>       &lt;\/div>       &lt;div class=\"col-auto\">         &lt;div class=\"input-group mb-3\">           &lt;span class=\"input-group-text\" id=\"message\">Message&lt;\/span>           &lt;input type=\"text\" class=\"form-control\" placeholder=\"Message\" name=\"message\">         &lt;\/div>       &lt;\/div>       &lt;div class=\"col-auto\">         &lt;button type=\"submit\" class=\"btn btn-primary mb-3\">Send&lt;\/button>       &lt;\/div>     &lt;\/form>   &lt;\/div> &lt;\/template> <\/code><\/pre>\n<p>Vue \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u0438 HTML-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u0441 \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u0434\u0430\u043d\u043d\u044b\u0445, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <code>script<\/code>, \u043d\u043e \u043f\u043e\u043a\u0430 \u0442\u0430\u043a\u0430\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a Vue \u043d\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f. \u0414\u043b\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0448\u0430\u0433\u043e\u0432.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0432\u0432\u043e\u0434\u0438\u043c \u0438\u043c\u044f \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"json\">data() {     return {       name: '',       message: '',     }   },<\/code><\/pre>\n<p>\u0438 \u043f\u0440\u0438\u0432\u044f\u0436\u0435\u043c \u0438\u0445 \u043a HTML-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435:<\/p>\n<pre><code class=\"xml\">... \u00a0&lt;input type=\"text\" class=\"form-control\" placeholder=\"Name\" name=\"name\" v-model=\"name\"> ...<\/code><\/pre>\n<p>\u0412 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0438\u043c\u0435\u043d\u0438 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443 <code>v-model=\"name\"<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0433\u043e\u0432\u043e\u0440\u0438\u0442 Vue \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u044d\u0442\u043e \u043f\u043e\u043b\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c <code>name<\/code> \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <code>data<\/code>. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043c \u0438 \u0441 \u043f\u043e\u043b\u0435\u043c \u0432\u0432\u043e\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f (<code>message<\/code>).<\/p>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong><\/p>\n<p>Vue.js \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043c\u043e\u0434\u0435\u043b\u044c MVVM (\u00abModel \u2192 View \u2192 ViewModel\u00bb \u0438\u043b\u0438 \u00ab\u041c\u043e\u0434\u0435\u043b\u044c \u2192 \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u2192 \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438\u00bb), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0432 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0438 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0439 MVC \u0441 \u043e\u0442\u043b\u0438\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u0432 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445: \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0435\u0435 \u0432 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u2014 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430, \u0430 \u043f\u0440\u0430\u0432\u043a\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u043e\u0442\u0440\u0430\u0437\u0438\u0442\u0441\u044f \u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.<\/p>\n<\/blockquote>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"json\">methods: {     send: function()     {       axios.get('\/api\/remember', {         params: {           name: this.name,           message: this.message         }       }).catch(error => alert(error));     },   },<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/api\/remember<\/code> \u0438 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u0432\u043e \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u043c \u043e\u043a\u043d\u0435, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a.<\/p>\n<p>\u0421\u0432\u044f\u0436\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<pre><code class=\"xml\">... &lt;button v-on:click=\"send\" type=\"submit\" class=\"btn btn-primary mb-3\">Send&lt;\/button> ...<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0411\u0414, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u044d\u0442\u043e\u043c \u0436\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043e\u0448\u043a\u043e \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0411\u0414 \u0438\u043b\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0432 \u043d\u0435\u0439 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u0444\u043e\u0440\u043c\u044b \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 \u0432\u0432\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 <code>say.html<\/code><strong> <\/strong>\u0438\u0437 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430:<\/p>\n<pre><code class=\"xml\">    &lt;div class=\"container mt-5\">       &lt;h2 class=\"text-center\">Messages from talkers&lt;\/h2>       &lt;button v-on:click=\"get\" type=\"button\" class=\"btn btn-outline-success mb-2\">\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438&lt;\/button>        &lt;div class=\"alert alert-warning\" role=\"alert\" v-if=\"error\">         Nothing to show!       &lt;\/div>        &lt;table class=\"table\" v-else>         &lt;thead>         &lt;th>Name&lt;\/th>         &lt;th>Message&lt;\/th>         &lt;\/thead>         &lt;tbody>         &lt;tr v-for=\"talker in talkers.Messages\" :key=\"talker.Name\">           &lt;td>{{ talker.Name }}&lt;\/td>           &lt;td>{{ talker.Message }}&lt;\/td>         &lt;\/tr>         &lt;\/tbody>       &lt;\/table>     &lt;\/div><\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>\u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0443\u0431\u0440\u0430\u043d\u044b \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u043e\u043a \u2014 \u043e\u043d\u0438 \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u044b \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443 <em>v-for<\/em> Vue.js, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0443\u044e \u043f\u0435\u0440\u0435\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0438\u0436\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 \u0411\u0414 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u0442;<\/p>\n<\/li>\n<li>\n<p>\u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u043e\u0439 <em>v-if<\/em>, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0449\u0435\u0439 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0444\u043b\u0430\u0433\u0430 <code>error<\/code><strong>:<\/strong> \u0435\u0441\u043b\u0438 \u043e\u043d \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 <code>true<\/code>, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u0435\u0441\u043b\u0438 \u0432 <code>false<\/code> \u2014 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p><strong>\u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435!<\/strong><\/p>\n<p>\u0412\u0430\u0436\u043d\u043e \u0441\u043e\u0431\u043b\u044e\u0441\u0442\u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u043e\u0432 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u043c\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430\u043c\u0438 \u2014 \u0438\u043d\u0430\u0447\u0435 \u0432\u0441\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c.<\/p>\n<\/blockquote>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"json\">  data() {     return {       name: '',       message: '',       talkers: [],       error: true     }   },   methods: {     send: function()     {       axios.get('\/api\/remember', {         params: {           name: this.name,           message: this.message         }       }).catch(error => alert(error));     },     get: function () {       axios.get(\"\/api\/say\")           .then(response => {             this.talkers = response.data;             this.error = false         })     }   }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u0432 \u0440\u0430\u0437\u0434\u0435\u043b <code>data<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043c\u0430\u0441\u0441\u0438\u0432 <code>talkers<\/code> \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0432 <code>methods<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>get<\/code> \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0431\u044d\u043a\u0435\u043d\u0434\u0430, \u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 <code>talkers<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u043b\u0430\u0433 <code>error<\/code> \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 <code>false<\/code>.<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong><\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u00ab\u0434\u043b\u044f \u0433\u0430\u043b\u043e\u0447\u043a\u0438\u00bb \u0441 \u0446\u0435\u043b\u044c\u044e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u00ab\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u2014 \u0443\u0431\u0440\u0430\u043b\u0438 \u0444\u043b\u0430\u0433\u00bb \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043b\u0438\u0431\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u043b\u0438\u0431\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0412 \u0438\u0434\u0435\u0430\u043b\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0443\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<\/blockquote>\n<details class=\"spoiler\">\n<summary>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 HelloWorld \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">&lt;template>   &lt;div class=\"container mt-5\">     &lt;form class=\"row g-3\">       &lt;div class=\"col-auto\">         &lt;div class=\"input-group mb-3\">           &lt;span class=\"input-group-text\" id=\"name\">Name&lt;\/span>           &lt;input type=\"text\" class=\"form-control\" placeholder=\"Name\" name=\"name\" v-model=\"name\">         &lt;\/div>       &lt;\/div>       &lt;div class=\"col-auto\">         &lt;div class=\"input-group mb-3\">           &lt;span class=\"input-group-text\" id=\"message\">Message&lt;\/span>           &lt;input type=\"text\" class=\"form-control\" placeholder=\"Message\" name=\"message\" v-model=\"message\">         &lt;\/div>       &lt;\/div>       &lt;div class=\"col-auto\">         &lt;button v-on:click=\"send\" type=\"submit\" class=\"btn btn-primary mb-3\">Send&lt;\/button>       &lt;\/div>     &lt;\/form>     &lt;div class=\"container mt-5\">       &lt;h2 class=\"text-center\">Messages from talkers&lt;\/h2>       &lt;button v-on:click=\"get\" type=\"button\" class=\"btn btn-outline-success mb-2\">\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438&lt;\/button>        &lt;div class=\"alert alert-warning\" role=\"alert\" v-if=\"error\">         Nothing to show!       &lt;\/div>        &lt;table class=\"table\" v-else>         &lt;thead>         &lt;th>Name&lt;\/th>         &lt;th>Message&lt;\/th>         &lt;\/thead>         &lt;tbody>         &lt;tr v-for=\"talker in talkers.Messages\" :key=\"talker.Name\">           &lt;td>{{ talker.Name }}&lt;\/td>           &lt;td>{{ talker.Message }}&lt;\/td>         &lt;\/tr>         &lt;\/tbody>       &lt;\/table>     &lt;\/div>   &lt;\/div>  &lt;\/template>  &lt;script> import axios from 'axios'; export default {   name: 'HelloWorld',   props: {     msg: String   },   data() {     return {       name: '',       message: '',       talkers: [],       error: true     }   },   methods: {     send: function()     {       axios.get('\/api\/remember', {         params: {           name: this.name,           message: this.message         }       }).catch(error => alert(error));     },     get: function () {       axios.get(\"\/api\/say\")           .then(response => {             this.talkers = response.data;             this.error = false         })     }   } } &lt;\/script>  &lt;style>&lt;\/style><\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<h2>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f<\/h2>\n<p>\u0421 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u0438 \u0435\u0433\u043e \u0442\u043e\u0436\u0435. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Dockerfile \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>frontend<\/code>:<\/p>\n<pre><code class=\"bash\"># \u042d\u0442\u0430\u043f \u0441\u0431\u043e\u0440\u043a\u0438 (build stage). FROM node:lts-alpine as build-stage WORKDIR \/app COPY frontend\/package*.json .\/ RUN npm install COPY frontend\/. . RUN npm run build   # \u042d\u0442\u0430\u043f production (production-stage). FROM nginx:stable-alpine as production-stage COPY --from=build-stage \/app\/dist \/usr\/share\/nginx\/html EXPOSE 80 CMD [\"nginx\", \"-g\", \"daemon off;\"]<\/code><\/pre>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u043c \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043c\u0443\u043b\u044c\u0442\u0438\u0441\u0442\u0435\u0439\u0434\u0436-\u0441\u0431\u043e\u0440\u043a\u0443. \u0412 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u0430\u0442\u0435\u043c \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0447\u0438\u0441\u0442\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441 nginx.<\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u0438\u043c Dockerfile \u0431\u044d\u043a\u0435\u043d\u0434\u0430, \u0443\u043a\u0430\u0437\u0430\u0432 \u043d\u043e\u0432\u044b\u0439 \u043f\u0443\u0442\u044c \u0438 \u0443\u0431\u0440\u0430\u0432 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432:<\/p>\n<pre><code class=\"bash\"># \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0443\u043f\u0435\u043d\u0447\u0430\u0442\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u043e\u0431\u0440\u0430\u0437\u0430 (multi-stage build). # \u041e\u0431\u0440\u0430\u0437, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442. FROM golang:1.18-alpine AS build # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c curl \u0438 tar. RUN apk add curl tar # \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. COPY backend\/. \/app WORKDIR \/app # \u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u0443 migrate \u0438 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0430\u0440\u0445\u0438\u0432. RUN curl -L https:\/\/github.com\/golang-migrate\/migrate\/releases\/download\/v4.16.2\/migrate.linux-amd64.tar.gz | tar xvz # \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0443\u0436\u043d\u044b\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432. RUN go mod download # \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. RUN go build -o \/goapp cmd\/main.go  # \u041e\u0431\u0440\u0430\u0437, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435. FROM alpine:latest WORKDIR \/ # \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0438\u0437 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u0440\u043e\u0435\u043a\u0442\u0430. COPY --from=build \/goapp \/goapp # \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0438\u0437 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0430 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0443\u0442\u0438\u043b\u0438\u0442\u044b migrate \u0438 \u0441\u0445\u0435\u043c\u044b \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438. COPY --from=build \/app\/migrate \/migrations\/migrate COPY backend\/db\/migrations \/migrations\/schemes EXPOSE 8080 ENTRYPOINT [\"\/goapp\"]<\/code><\/pre>\n<p>\u0423\u0434\u0430\u043b\u0438\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>backend\/templates<\/code> \u2014 \u043e\u043d \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u0444\u0430\u0439\u043b <code>werf.yaml<\/code> \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c (\u043a\u0430\u043a \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/759040\/#%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%BA%D0%B0-%D0%BA-%D1%80%D0%B0%D0%B7%D0%B2%D0%B5%D1%80%D1%82%D1%8B%D0%B2%D0%B0%D0%BD%D0%B8%D1%8E\"><u>\u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0446\u0438\u043a\u043b\u0430<\/u><\/a>):<\/p>\n<pre><code class=\"yaml\">project: habr-app configVersion: 1  --- image: backend dockerfile: backend\/Dockerfile  --- image: frontend dockerfile: frontend\/Dockerfile<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>.helm<\/code> \u0438\u0437 <code>backend<\/code> \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u043c Deployment \u0431\u044d\u043a\u0435\u043d\u0434\u0430, \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043e\u0431\u0440\u0430\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 <code>app<\/code> \u043d\u0430 <code>backend<\/code> \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432 <code>werf.yaml<\/code><strong> <\/strong>\u0438 \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u2014\u00a0\u043f\u043e \u043d\u0438\u043c \u0431\u0443\u0434\u0443\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043c\u0435\u043d\u0430 <em>\u043f\u043e\u0434\u043e\u0432<\/em> \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435.<\/p>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <code>deployment-backend.yaml<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c:<\/p>\n<pre><code class=\"yaml\">apiVersion: apps\/v1 kind: Deployment metadata:   name: habr-app-backend spec:   replicas: 1   selector:     matchLabels:       app: habr-app-backend   template:     metadata:       labels:         app: habr-app-backend     spec:       imagePullSecrets:       - name: registrysecret       containers:       - name: app-backend         image: {{ .Values.werf.image.backend }}         ports:         - containerPort: 8080         env:           - name: GIN_MODE             value: \"release\"           - name: DB_TYPE             value: \"mysql\"           - name: DB_NAME             value: \"habr-app\"           - name: DB_USER             value: \"root\"           - name: DB_PASSWD             value: \"password\"           - name: DB_HOST             value: \"mysql\"           - name: DB_PORT             value: \"3306\"<\/code><\/pre>\n<p>Service \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c, \u0437\u0430\u043c\u0435\u043d\u0438\u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043d\u043e\u0432\u043e\u0435, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0432 Deployment\u2019\u0435\u00a0 \u0432\u044b\u0448\u0435:<\/p>\n<pre><code class=\"yaml\">apiVersion: v1 kind: Service metadata:   name: habr-app-backend spec:   selector:     app: habr-app-backend   ports:   - name: http     port: 8080<\/code><\/pre>\n<p>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c Deployment \u0438 Service \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430.<\/p>\n<p>Deployment \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u0435\u043d Deployment\u2019\u0443 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u2014 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0438 \u0441\u0430\u043c\u043e\u0433\u043e Deployment\u2019\u0430 \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0430 <code>werf.yaml<\/code> \u0438 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0440\u0430\u0437\u0438\u0442\u044c \u0441\u0443\u0442\u044c \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"yaml\">apiVersion: apps\/v1 kind: Deployment metadata:   name: habr-app-frontend spec:   replicas: 1   selector:     matchLabels:       app: habr-app-frontend   template:     metadata:       labels:         app: habr-app-frontend     spec:       imagePullSecrets:       - name: registrysecret       containers:       - name: app-frontend         image: {{ .Values.werf.image.frontend }}         ports:         - containerPort: 80 --- apiVersion: v1 kind: Service metadata:   name: habr-app-frontend spec:   selector:     app: habr-app-frontend   ports:     - name: http       port: 80<\/code><\/pre>\n<p>\u0418\u0437\u043c\u0435\u043d\u0438\u043c Ingress-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/<\/code>, \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u0438\u0441\u044c \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043d\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/api<\/code> \u2014 \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434:<\/p>\n<pre><code class=\"yaml\">apiVersion: networking.k8s.io\/v1 kind: Ingress metadata:   annotations:     kubernetes.io\/ingress.class: nginx   name: habr-app spec:   rules:   - host: habrapp.example.com     http:       paths:       - path: \/         pathType: Prefix         backend:           service:             name: habr-app-frontend             port:               number: 80       - path: \/api         pathType: Prefix         backend:           service:             name: habr-app-backend             port:               number: 8080   tls:     - hosts:         - habrapp.example.com       secretName: habr-app-tls<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0437\u0430 \u0432 Job, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u0411\u0414:<\/p>\n<pre><code class=\"yaml\">image: {{ .Values.werf.image.backend }}<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043e \u0438 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e.<\/p>\n<h2>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u0438<\/h2>\n<p>\u0417\u0430\u043a\u043e\u043c\u043c\u0438\u0442\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u043a\u0430\u0442\u0438\u043c \u0438\u0445 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">werf converge --repo &lt;\u0418\u041c\u042f \u041f\u041e\u041b\u042c\u0417\u041e\u0412\u0410\u0422\u0415\u041b\u042f DOCKER HUB>\/habr-app<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0451 \u0441\u043e\u0431\u0440\u0430\u043b\u043e\u0441\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u043e\u0441\u044c, \u0443\u0432\u0438\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code class=\"bash\">Release \"habr-app\" has been upgraded. Happy Helming! NAME: habr-app LAST DEPLOYED: Wed Aug 23 14:00:31 2023 LAST PHASE: rollout LAST STAGE: 0 NAMESPACE: habr-app STATUS: deployed REVISION: 3 TEST SUITE: None Running time 15.52 seconds<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/91f\/622\/c74\/91f622c74c1cbd823ce3b03083d97549.png\" width=\"1600\" height=\"447\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/91f\/622\/c74\/91f622c74c1cbd823ce3b03083d97549.png\"\/><\/figure>\n<p>\u0417\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u043e\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u043e\u0441\u044c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/be4\/ffb\/1ec\/be4ffb1ec41964d8922da310d69d6473.png\" width=\"1600\" height=\"471\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/be4\/ffb\/1ec\/be4ffb1ec41964d8922da310d69d6473.png\"\/><\/figure>\n<p>\u0418 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u0438 \u0431\u044d\u043a\u0435\u043d\u0434 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442.<\/p>\n<h2>\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f<\/h2>\n<p>\u041c\u044b \u043f\u043b\u0430\u0432\u043d\u043e \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c\u0443 \u0432\u043e\u043f\u0440\u043e\u0441\u0443 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u0414\u0430, \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438 \u043e\u043d\u043e \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0431\u0435\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD, \u043e\u0447\u0435\u043d\u044c \u0443\u0442\u043e\u043c\u0438\u0442\u0435\u043b\u044c\u043d\u043e. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u0434 \u0440\u0443\u043a\u0430\u043c\u0438 \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0442\u0435\u0440, \u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u043d\u0430\u0434\u043e.<\/p>\n<p>\u0412 \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u044f\u043c\u043e \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u0435\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430.<\/p>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong><\/p>\n<p>\u0420\u0430\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0430\u043a\u0442\u0443\u0430\u043b\u0435\u043d \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0438\u043b\u0438 \u0441\u0440\u0435\u0434\u043d\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0415\u0441\u043b\u0438 \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e \u0442\u044f\u0436\u0435\u043b\u043e\u043c \u0441\u043e\u0444\u0442\u0435, \u043e\u0434\u043d\u0430 \u0441\u0431\u043e\u0440\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0438\u043b\u0438 \u0441\u043e\u0442\u043d\u0438 \u043c\u0438\u043d\u0443\u0442 \u043d\u0430 \u043c\u043e\u0449\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u2014 \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u0443\u0436\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0443\u0434\u043e\u0431\u043d\u044b\u043c.<\/p>\n<\/blockquote>\n<h3>\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0431\u044d\u043a\u0435\u043d\u0434 \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c. \u0417\u0430\u043f\u0440\u043e\u0441\u044b \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0430 API \u0431\u044d\u043a\u0435\u043d\u0434\u0430, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e\u0441\u044f \u043f\u043e \u0442\u043e\u043c\u0443 \u0436\u0435 \u0430\u0434\u0440\u0435\u0441\u0443, \u0447\u0442\u043e \u0438 \u0441\u0430\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u044b\u0448\u0435, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043e \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>\/<\/code>, \u0430 \u0435\u0433\u043e API \u2014 <code>\/api\/*<\/code><em>. <\/em>\u0418 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u043d\u0438\u0445 \u0434\u0432\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u0438 \u0431\u044d\u043a\u0435\u043d\u0434, \u043d\u043e\u2026 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0435 \u0434\u0430\u0441\u0442 \u044d\u0442\u043e\u0433\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c. \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0431\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0435 80, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0438\u0445 \u2014 \u0442\u043e\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0441\u043f\u0435\u0435\u0442 \u0437\u0430\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u043f\u043e\u0440\u0442. \u0415\u0441\u043b\u0438 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u043e\u0440\u0442\u044b, \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 API \u043d\u0435 \u043f\u043e\u0439\u0434\u0443\u0442 \u043a\u0443\u0434\u0430 \u043d\u0443\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a API \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>localhost:8080\/api\/<\/code> \u0432\u043c\u0435\u0441\u0442\u043e <code>\/localhost\/api\/*<\/code>. \u041f\u043b\u044e\u0441 \u0435\u0449\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 MySQL, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043d\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440.<\/p>\n<p>\u0412\u044b\u0439\u0442\u0438 \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u2014 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445, \u0430 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e \u0434\u0443\u0448\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0430\u043c.<\/p>\n<h3>\u0421\u043f\u043e\u0441\u043e\u0431 \u21161 \u2014 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 Kubernetes \u043d\u0430 minikube<\/h3>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u043c\u0435\u043d\u044b \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 Kubernetes (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/kubernetes.io\/ru\/docs\/tasks\/tools\/install-minikube\/\"><u>minikube<\/u><\/a>) \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043d\u0435\u043c. \u041e\u0431\u044b\u0447\u043d\u043e \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Docker \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0432\u043e\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u043d\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043d \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c.<\/p>\n<p>\u0418\u0437 \u043f\u043b\u044e\u0441\u043e\u0432 \u0437\u0434\u0435\u0441\u044c: \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0435 Helm-\u0447\u0430\u0440\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0432 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. \u041d\u043e \u0435\u0441\u0442\u044c \u0438 \u043c\u0438\u043d\u0443\u0441\u044b: \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f registry \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0438 \u0441\u043e\u043f\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445. \u0417\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u043e\u0439 \u0436\u0435 \u0441\u0430\u043c\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439, \u0447\u0442\u043e \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 (\u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043d\u0430 <code>minikube<\/code>).<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c minikube <a href=\"https:\/\/minikube.sigs.k8s.io\/docs\/start\/\"><u>\u043f\u043e \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438<\/u><\/a>.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440:<\/p>\n<pre><code class=\"bash\">$ minikube start --driver=docker ?  minikube v1.31.2 \u043d\u0430 Darwin 13.6 (arm64) \u2728  Automatically selected the docker driver ?  Using Docker Desktop driver with root privileges ?  \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f control plane \u0443\u0437\u0435\u043b minikube \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 minikube ?  \u0421\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 ... ?  Creating docker container (CPUs=2, Memory=4000MB) ... ?  \u041f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f Kubernetes v1.27.4 \u043d\u0430 Docker 24.0.4 ...     \u25aa Generating certificates and keys ...     \u25aa Booting up control plane ...     \u25aa Configuring RBAC rules ... ?  Configuring bridge CNI (Container Networking Interface) ... ?  \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b Kubernetes \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f ...     \u25aa \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437 gcr.io\/k8s-minikube\/storage-provisioner:v5 ?  \u0412\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f: storage-provisioner, default-storageclass ?  \u0413\u043e\u0442\u043e\u0432\u043e! kubectl \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \"minikube\" \u0438 \"default\" \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430 \u0438\u043c\u0435\u043d \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e<\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0442\u0435\u0440 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0441\u044f.<\/p>\n<p>\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u043c \u043f\u043b\u0430\u0433\u0438\u043d Ingress-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430:<\/p>\n<pre><code class=\"bash\">$ minikube addons enable ingress ?  ingress is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub. You can view the list of minikube maintainers at: https:\/\/github.com\/kubernetes\/minikube\/blob\/master\/OWNERS ?  After the addon is enabled, please run \"minikube tunnel\" and your ingress resources would be available at \"127.0.0.1\"     \u25aa \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437 registry.k8s.io\/ingress-nginx\/kube-webhook-certgen:v20230407     \u25aa \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437 registry.k8s.io\/ingress-nginx\/kube-webhook-certgen:v20230407     \u25aa \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437 registry.k8s.io\/ingress-nginx\/controller:v1.8.1 ?  Verifying ingress addon... ?  The 'ingress' addon is enabled<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043d\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u0438\u043c\u0435\u043d \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">$ kubectl create namespace habr-app namespace\/habr-app created<\/code><\/pre>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong><\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0430 \u0432\u0430\u0448\u0435\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d <a href=\"https:\/\/kubernetes.io\/ru\/docs\/tasks\/tools\/install-kubectl\/\"><u>kubectl<\/u><\/a>, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043b\u0438\u0431\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0432 minikube (\u0442\u0440\u0435\u0442\u0438\u0439 \u0448\u0430\u0433 <a href=\"https:\/\/minikube.sigs.k8s.io\/docs\/start\/\"><u>\u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438<\/u><\/a> \u043f\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435), \u043b\u0438\u0431\u043e <a href=\"https:\/\/werf.io\/documentation\/v1.2\/reference\/cli\/werf_kubectl_config_set_context.html\"><u>\u0443\u0442\u0438\u043b\u0438\u0442\u043e\u0439 werf<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043c\u0435\u0435\u0442 \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<\/blockquote>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0435\u0433\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p>\n<pre><code class=\"bash\">$ kubectl config set-context minikube --namespace=habr-app Context \"minikube\" modified.<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c Secret \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a container registry:<\/p>\n<pre><code class=\"bash\">kubectl create secret docker-registry registrysecret \\   --docker-server='https:\/\/index.docker.io\/v1\/' \\   --docker-username='&lt;\u0418\u041c\u042f \u041f\u041e\u041b\u042c\u0417\u041e\u0412\u0410\u0422\u0415\u041b\u042f DOCKER HUB>' \\   --docker-password='&lt;\u041f\u0410\u0420\u041e\u041b\u042c \u041f\u041e\u041b\u042c\u0417\u041e\u0412\u0410\u0422\u0415\u041b\u042f DOCKER HUB>'<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u043e\u0439\u0442\u0438 \u0432 registry:<\/p>\n<pre><code class=\"bash\">werf cr login -u username -p password https:\/\/index.docker.io\/v1\/<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c DNS-\u0438\u043c\u044f \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u2014 \u043f\u0440\u043e\u043f\u0438\u0448\u0435\u043c \u0435\u0433\u043e \u0432 <code>\/etc\/hosts<\/code>. \u0414\u043b\u044f Linux \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">echo \"$(minikube ip) habrapp.example.com\" | sudo tee -a \/etc\/hosts<\/code><\/pre>\n<p>\u0414\u043b\u044f macOS \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c Docker Desktop \u0432\u043c\u0435\u0441\u0442\u043e <code>$(minikube ip)<\/code> \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432\u0430\u0448\u0435\u0439 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b:<\/p>\n<pre><code class=\"bash\">echo \"127.0.0.1 habrapp.example.com\" | sudo tee -a \/etc\/hosts<\/code><\/pre>\n<p>\u0417\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:<\/p>\n<pre><code class=\"bash\">werf converge --repo &lt;\u0418\u041c\u042f \u041f\u041e\u041b\u042c\u0417\u041e\u0412\u0410\u0422\u0415\u041b\u042f DOCKER HUB>\/habr-app<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u0432 \u043a\u043e\u043d\u0446\u0435 \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0442\u0430\u043a\u043e\u0435:<\/p>\n<pre><code class=\"bash\">... \u2502 \u250c Status progress \u2502 \u2502 JOB                                                                                                                                                       ACTIVE                       DURATION                        SUCCEEDED\/FAILED \u2502 \u2502 setup-and-migrate-db-rev1                                                                                                                                 0                            88s                             0->1\/0                                          \u21b5 \u2502 \u2502 \u2502 \u2502 \u2502   POD                                                         READY                 RESTARTS                      STATUS \u2502 \u2502 \u2514\u2500\u2500 and-migrate-db-rev1-2dn7p                                   0\/1                   0                             Completed \u2502 \u2514 Status progress \u2514 Waiting for resources to become ready (86.54 seconds)  NAME: habr-app LAST DEPLOYED: Tue Oct 31 13:47:56 2023 LAST PHASE: rollout LAST STAGE: 0 NAMESPACE: habr-app STATUS: deployed REVISION: 1 TEST SUITE: None Running time 175.69 seconds<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u043e \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 minikube. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0435\u0440\u0435\u0439\u0434\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043f\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443 \u0432 <code>hosts<\/code> \u0430\u0434\u0440\u0435\u0441\u0443:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/36d\/742\/bd2\/36d742bd2a248f6dc3cd3defa38082b8.png\" width=\"1084\" height=\"255\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/36d\/742\/bd2\/36d742bd2a248f6dc3cd3defa38082b8.png\"\/><\/figure>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong><\/p>\n<p>\u0412 macOS \u0441 Docker Desktop \u043f\u0435\u0440\u0435\u0434 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0443\u043d\u043d\u0435\u043b\u044c \u0434\u043b\u044f minikube, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 Ingress-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a \u043d\u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <code>127.0.0.1<\/code>. \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>minikube tunnel<\/code>, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043e\u043a\u043d\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430. \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u0438\u043b\u0435\u0433\u0438\u0439 \u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442 \u043f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/blockquote>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0443\u043d\u043d\u0435\u043b\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u043d\u0430\u0436\u0430\u0432 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448 <code>Ctrl + C<\/code>, \u043d\u0430\u0445\u043e\u0434\u044f\u0441\u044c \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u0441 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u043c \u0442\u0443\u043d\u043d\u0435\u043b\u0435\u043c.\u00a0<\/p>\n<h3>\u0421\u043f\u043e\u0441\u043e\u0431 \u21162 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Docker Compose<\/h3>\n<p>\u0423 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u0441\u0438\u043b\u044c\u043d\u044b\u0439 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u043a: \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0432\u0441\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 registry \u0438 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435. <\/p>\n<p>\u0414\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0441 Go-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u044d\u0442\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u2014 \u0432\u0435\u0434\u044c \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435. \u041d\u043e \u0434\u043b\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c \u0442\u0430\u043a\u043e\u0439 \u043f\u0443\u0442\u044c \u043d\u0435\u0443\u0434\u043e\u0431\u0435\u043d. npm \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0436\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u044b hot reload (\u0433\u043e\u0440\u044f\u0447\u0435\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438), \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0435\u0437 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f (\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043e\u043d\u043e \u0435\u0441\u0442\u044c, \u043d\u043e \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043f\u043e\u043b\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0437\u0430\u043c\u0435\u0442\u043d\u043e).<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2014 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0435\u043c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 <a href=\"https:\/\/docs.docker.com\/compose\/\"><u>Docker Compose<\/u><\/a> \u0438 \u0442\u043e\u0436\u0435 \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c werf. Docker Compose \u2014 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0432 \u0441\u043e\u0441\u0442\u0430\u0432 Docker \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 <code>werf.yaml<\/code> \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0430 Vue-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"yaml\">... --- image: frontend-compose dockerfile: frontend\/Dockerfile target: build-stage<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0441\u0442\u0430\u0434\u0438\u044e \u043e\u0431\u0440\u0430\u0437\u0430 \u0438\u0437 Dockerfile \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430: <code>build-stage<\/code>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0444\u0430\u0439\u043b <code>docker-compose.yml<\/code>:<\/p>\n<pre><code class=\"yaml\">version: \"3.7\" services:   frontend:     container_name: frontend     image: $WERF_FRONTEND_COMPOSE_DOCKER_IMAGE_NAME     working_dir: \"\/app\"     command: npm run serve     volumes:       - \".\/frontend:\/app\"     networks:       - nginx_net    backend:     container_name: backend     image: $WERF_BACKEND_DOCKER_IMAGE_NAME     networks:       - nginx_net       - backend_net     environment:       - GIN_MODE=release       - DB_TYPE=mysql       - DB_NAME=habr-app       - DB_USER=root       - DB_PASSWD=password       - DB_HOST=mysql       - DB_PORT=3306     depends_on:       mysql:         condition: service_started   mysql:     image: mysql:8     restart: always     environment:       - MYSQL_ROOT_PASSWORD=password       - MYSQL_DATABASE=habr-app     networks:       - backend_net     volumes:       - .\/mysql:\/var\/lib\/mysql   nginx:     container_name: nginx     image: nginx:stable-alpine     restart: unless-stopped     networks:       - nginx_net     volumes:       - .\/.configs\/nginx.conf:\/etc\/nginx\/conf.d\/default.conf     ports:       - \"80:80\"     command: '\/bin\/sh -c ''while :; do sleep 6h &amp; wait $${!}; nginx -s reload; done &amp; nginx -g \"daemon off;\"'''  networks:   nginx_net:     external: false   backend_net:     external: false<\/code><\/pre>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u0441\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430: <code>$WERF_BACKEND_DOCKER_IMAGE_NAME<\/code> \u0438 <code>$WERF_FRONTEND_COMPOSE_DOCKER_IMAGE_NAME<\/code>. \u041e\u043d\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0438\u0437 <code>werf.yaml<\/code>. \u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 werf \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442 \u0432 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u0442\u0435\u0433\u0438 \u0438\u043b\u0438 ID \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u0442.<\/p>\n<p>\u0412 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043c\u044b \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 <code>frontend<\/code> \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>\/app<\/code> \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043e\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0435\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430. \u0417\u0430\u0442\u0435\u043c \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u043d\u0430 <code>npm run serve<\/code>. \u042d\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0432 npm \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043d\u0430\u0448\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u041a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0443 MySQL \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f Volume, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0411\u0414. \u0420\u044f\u0434\u043e\u043c \u0441 \u0444\u0430\u0439\u043b\u043e\u043c docker-compose, \u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0434\u043b\u044f \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 <code>.gitignore<\/code>.<\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430\u043c\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f nginx \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0432\u0435\u0440\u0441-\u043f\u0440\u043e\u043a\u0441\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043c\u0435\u0436\u0434\u0443 <code>\/<\/code> \u0438 <code>\/api<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <code>volumes<\/code> \u043c\u044b \u043c\u043e\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b <code>nginx.conf<\/code> \u0434\u043b\u044f \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>.configs\/nginx.conf<\/code>:<\/p>\n<pre><code class=\"bash\">server {   listen 80;    server_name stats-informer;    client_max_body_size 50m;    location \/ {     resolver 127.0.0.11;     set $project http:\/\/frontend:8080;      proxy_pass $project;      proxy_http_version  1.1;     proxy_cache_bypass  $http_upgrade;      proxy_set_header Upgrade           $http_upgrade;     proxy_set_header Connection        \"upgrade\";     proxy_set_header Host              $host;     proxy_set_header X-Real-IP         $remote_addr;     proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;     proxy_set_header X-Forwarded-Proto $scheme;     proxy_set_header X-Forwarded-Host  $host;     proxy_set_header X-Forwarded-Port  $server_port;    }    location \/api\/ {       resolver 127.0.0.11;       set $project http:\/\/backend:8080;        proxy_pass $project;        proxy_http_version  1.1;       proxy_cache_bypass  $http_upgrade;        proxy_set_header Upgrade           $http_upgrade;       proxy_set_header Connection        \"upgrade\";       proxy_set_header Host              $host;       proxy_set_header X-Real-IP         $remote_addr;       proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;       proxy_set_header X-Forwarded-Proto $scheme;       proxy_set_header X-Forwarded-Host  $host;       proxy_set_header X-Forwarded-Port  $server_port;      } }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432 \u0444\u0430\u0439\u043b\u0435 docker-compose \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0434\u0432\u0435 \u0441\u0435\u0442\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432: <code>nginx_net<\/code> \u0438 <code>backend_net<\/code>. \u0412 \u043f\u0435\u0440\u0432\u0443\u044e \u0438\u043c\u0435\u044e\u0442 \u0434\u043e\u0441\u0442\u0443\u043f nginx \u0438 \u0431\u044d\u043a\u0435\u043d\u0434 \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0431\u044d\u043a\u0435\u043d\u0434 \u0438 \u0411\u0414.<\/p>\n<p>\u0412\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0443. \u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">werf compose up<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0441\u043e\u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0437\u044b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, nginx \u0438 MySQL \u0437\u0430\u0433\u0440\u0443\u0437\u044f\u0442\u0441\u044f \u0441 Docker\u00a0Hub, \u0430 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f.<\/p>\n<p>\u041d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u2014 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0411\u0414.<\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432 Docker:<\/p>\n<pre><code class=\"bash\">$ docker ps CONTAINER ID   IMAGE                                                                             COMMAND                  CREATED             STATUS             PORTS                 NAMES a9bc74606d42   habr-app:1935fb904d211c637e0fb5b0212bb992d435fb54c63b68fd8d2951bb-1692862816809   \"\/goapp\"                 About an hour ago   Up About an hour   8080\/tcp              backend 68713fd81022   nginx:stable-alpine                                                               \"\/docker-entrypoint.\u2026\"   About an hour ago   Up About an hour   0.0.0.0:80->80\/tcp    nginx bfe12808ade8   habr-app:9d323934c5233de86cbf4ac26f938419d3a1ac8055be8c23ea4d7212-1692863007929   \"\/docker-entrypoint.\u2026\"   About an hour ago   Up About an hour   80\/tcp                frontend 86725a5995ff   mysql:8 \"docker-entrypoint.s\u2026\"   About an hour ago   Up About an hour 3306\/tcp, 33060\/tcp habr-werf-local-stend-mysql-1<\/code><\/pre>\n<p>\u041d\u0430\u0439\u0434\u0435\u043c ID \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u043c \u2014 <code>a9bc74606d42<\/code>. \u0412\u043e\u0439\u0434\u0435\u043c \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"bash\">$ docker exec -ti a9bc74606d42 \/migrations\/migrate -database \"mysql:\/\/root:password@tcp(mysql:3306)\/habr-app\" -path \/migrations\/schemes up 1\/u create_talkers_table (20.315917ms)<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0440\u0430\u0431\u043e\u0442\u0435! \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435:<\/p>\n<pre><code class=\"bash\">werf compose up --docker-compose-command-options=\"-d\"<\/code><\/pre>\n<p>\u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442:<\/p>\n<pre><code class=\"bash\">Using werf config render file: \/private\/var\/folders\/t_\/zx9l_6896snf1qw2q6h1n0940000gn\/T\/werf-config-render-859276243 \u250c \u26f5 image frontend-compose [linux\/amd64] \u2502 Use previously built image for frontend-compose\/dockerfile \u2502      name: habr-app:8c7bf32a905c70f355bf1dbe1d7f0c2e606dd2d2191037c5f9529ec1-1698752438734 \u2502        id: 5fc2525a0fc9 \u2502   created: 2023-10-31 14:40:38.646684918 +0300 MSK \u2502      size: 328.6 MiB \u2502  platform: linux\/amd64 \u2514 \u26f5 image frontend-compose [linux\/amd64] (0.11 seconds)  \u250c \u26f5 image backend [linux\/amd64] \u2502 Use previously built image for backend\/dockerfile \u2502      name: habr-app:1935fb904d211c637e0fb5b0212bb992d435fb54c63b68fd8d2951bb-1698752435818 \u2502        id: c38113ce852c \u2502   created: 2023-10-31 14:40:35.732990167 +0300 MSK \u2502      size: 66.4 MiB \u2502  platform: linux\/amd64 \u2514 \u26f5 image backend [linux\/amd64] (0.08 seconds)  \u250c \u26f5 image frontend [linux\/amd64] \u2502 Use previously built image for frontend\/dockerfile \u2502      name: habr-app:9d323934c5233de86cbf4ac26f938419d3a1ac8055be8c23ea4d7212-1698752437277 \u2502        id: f08cb789a0d4 \u2502   created: 2023-10-31 14:40:37.190123376 +0300 MSK \u2502      size: 44.8 MiB \u2502  platform: linux\/amd64 \u2514 \u26f5 image frontend [linux\/amd64] (0.08 seconds) [+] Building 0.0s (0\/0)                                                                                                                                                                                                                         docker-container:happy_mendel [+] Running 4\/0  \u2714 Container app-mysql-1  Running                                                                                                                                                                                                                                        0.0s  \u2714 Container frontend     Running                                                                                                                                                                                                                                        0.0s  \u2714 Container nginx        Running                                                                                                                                                                                                                                        0.0s  \u2714 Container backend      Running<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0435\u0440\u0435\u0439\u0434\u044f \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <a href=\"http:\/\/localhost\/\"><u>http:\/\/localhost<\/u><\/a> \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9c8\/1d6\/cff\/9c81d6cffa435eec09b23fc80b79d1dd.png\" width=\"1600\" height=\"431\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9c8\/1d6\/cff\/9c81d6cffa435eec09b23fc80b79d1dd.png\"\/><\/figure>\n<p>\u0423\u0440\u0430! \u041e\u043d\u043e \u0438 \u043f\u0440\u0430\u0432\u0434\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442!<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0432\u0441\u0435 \u0431\u0435\u0437 \u043e\u043f\u0446\u0438\u0438 <code>--docker-compose-command-options=\"-d\"<\/code>, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Vue \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043d\u0435 \u0437\u0430\u0442\u0440\u0430\u0433\u0438\u0432\u0430\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440. \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u0443\u0432\u0438\u0434\u0438\u043c \u043b\u043e\u0433 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u0441\u0435\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043b\u043e\u0433 \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c:<\/p>\n<pre><code class=\"bash\">frontend     | frontend     | > frontend@0.1.0 serve frontend     | > vue-cli-service serve frontend     | frontend     |  INFO  Starting development server...  DONE  Compiled successfully in 15131ms1:16:28 PM frontend     |  frontend     |   App running at: frontend     |   - Local:   http:\/\/localhost:8080\/ frontend     |   - Network: http:\/\/172.19.0.2:8080\/ frontend     | frontend     |   Note that the development build is not optimized. frontend     |   To create a production build, run npm run build. frontend     | Build finished at 13:16:28 by 0.000s<\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fb8\/1c9\/7cb\/fb81c97cb06ffe0d1bab200d2e7b40c3.png\" width=\"1338\" height=\"367\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fb8\/1c9\/7cb\/fb81c97cb06ffe0d1bab200d2e7b40c3.png\"\/><\/figure>\n<p>\u0418\u0437\u043c\u0435\u043d\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u00abMessages from talkers\u00bb \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u00abMessages\u00bb \u0432 \u0444\u0430\u0439\u043b\u0435 <code>\/frontend\/src\/components\/HelloWorld.vue<\/code> \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0435\u0433\u043e. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0430 Vue-\u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<pre><code class=\"bash\">frontend     | frontend     | Compiling...  DONE  Compiled successfully in 4643ms1:20:27 PM frontend     |  frontend     |   App running at: frontend     |   - Local:   http:\/\/localhost:8080\/ frontend     |   - Network: http:\/\/172.19.0.2:8080\/ frontend     | Build finished at 13:20:27 by 0.000s<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a35\/5b5\/494\/a355b549474dde0f7927debeeb6187f5.png\" width=\"1346\" height=\"346\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a35\/5b5\/494\/a355b549474dde0f7927debeeb6187f5.png\"\/><\/figure>\n<p>\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u043e\u0441\u044c, \u0438 \u0437\u0430\u043d\u044f\u043b\u043e \u044d\u0442\u043e \u043e\u0442 \u0441\u0438\u043b\u044b \u043f\u0430\u0440\u0443 \u0441\u0435\u043a\u0443\u043d\u0434. \u0410 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u043b\u0441\u044f \u0431\u044b \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0434\u043e\u043b\u044c\u0448\u0435.<\/p>\n<h3>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438<\/h3>\n<p>\u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0431\u0440\u0430\u043d\u043e \u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e. \u041e\u0434\u043d\u0430\u043a\u043e \u043b\u044e\u0431\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043d\u0435\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0440\u0443\u0447\u043d\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0432 Git \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e, \u0434\u0430 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0432\u0438\u0434\u0435\u0442\u044c \u0441\u0440\u0430\u0437\u0443, \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0437\u0430\u043a\u043e\u043d\u043e\u043c\u0435\u0440\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443 werf \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u0432\u0430 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u043b\u0430\u0433\u0430:<\/p>\n<ul>\n<li>\n<p><code>--dev<\/code> \u2014 \u0432 \u044d\u0442\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0437\u0430\u043f\u0443\u0441\u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u0432\u0435\u0442\u043a\u0443, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e werf \u0441\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043d\u043d\u0443\u044e \u0432\u0435\u0442\u043a\u0443 \u0438 \u043a\u043e\u043c\u043c\u0438\u0442 \u0432 \u043d\u0435\u0435, \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u0442 \u0441\u0431\u043e\u0440\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p><code>--follow<\/code> \u2014 \u0432 \u044d\u0442\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 werf \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0443 \u0438 \u043f\u0435\u0440\u0435\u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043a\u043e\u043c\u043c\u0438\u0442\u0435; \u0437\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0437\u0430\u0434\u0430\u043d \u0444\u043b\u0430\u0433 <code>--dev<\/code>, \u0442\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0435 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445, \u0434\u0430\u0436\u0435 untracked-\u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u044f \u044d\u0442\u0438 \u0434\u0432\u0430 \u0444\u043b\u0430\u0433\u0430, \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f:\u00a0<\/p>\n<ul>\n<li>\n<p>\u0441\u0431\u043e\u0440\u043a\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u043c\u043c\u0438\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 Git;<\/p>\n<\/li>\n<li>\n<p>\u0441\u0431\u043e\u0440\u043a\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043b\u044e\u0431\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u0432 \u0442\u0430\u043a\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0444\u043b\u0430\u0433\u0430\u043c\u0438:<\/p>\n<pre><code class=\"bash\">werf compose up --dev --follow<\/code><\/pre>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u0434\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/flant\/examples\/tree\/master\/2023\/08-werf-local-dev\"><u>\u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/u><\/a>.<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0440\u0430\u0437\u0431\u0438\u0432 \u0435\u0433\u043e \u043d\u0430 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0438 \u0431\u044d\u043a\u0435\u043d\u0434, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 Kubernetes, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432\u0441\u0435\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u0422\u0430\u043a\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 werf.<\/p>\n<h2>P.\u202fS.<\/h2>\n<p>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/ru.werf.io\/guides.html\"><u>\u0421\u0430\u043c\u043e\u0443\u0447\u0438\u0442\u0435\u043b\u044c \u00ab\u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c CI\/CD \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 Kubernetes\u00bb<\/u><\/a>. \u0421\u0430\u043c\u043e\u0443\u0447\u0438\u0442\u0435\u043b\u044c \u0440\u0430\u0437\u0431\u0438\u0442 \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u0442\u0435\u0439: \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 Node.js, Java Spring Boot, Django, Python, Go, Ruby on Rails, Laravel. \u0412 \u0441\u0430\u043c\u043e\u0443\u0447\u0438\u0442\u0435\u043b\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0439\u0442\u0438 \u0432\u0435\u0441\u044c \u043f\u0443\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0432 production.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/t.me\/werf_ru\"><u>\u0427\u0430\u0442 werf<\/u><\/a>, \u0433\u0434\u0435 \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u2014 \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u043b\u0438 \u043f\u043e\u0439\u0434\u0435\u0442 \u043d\u0435 \u0442\u0430\u043a.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0438\u0442\u0430\u0439\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u0432 \u043d\u0430\u0448\u0435\u043c \u0431\u043b\u043e\u0433\u0435:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/759040\/\"><u>\u0420\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 Kubernetes \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c Deckhouse c \u043f\u043e\u043c\u043e\u0449\u044c\u044e werf<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/597001\/\"><u>\u041f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438 \u0441 werf: \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438 \u0434\u0435\u043f\u043b\u043e\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 Kubernetes<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/597277\/\"><u>\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432 Kubernetes \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e werf 1.2 \u0438 minikube<\/u><\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/flant\/news\/752166\/\"><u>\u041f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0441\u0430\u043c\u043e\u0443\u0447\u0438\u0442\u0435\u043b\u044c \u043f\u043e CI\/CD \u0438 Kubernetes \u0434\u043b\u044f Go-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b werf<\/u><\/a><\/p>\n<\/li>\n<\/ul>\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\/771678\/\"> https:\/\/habr.com\/ru\/articles\/771678\/<\/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<figure class=\"full-width\"><\/figure>\n<p>\u0412\u043d\u043e\u0441\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0442\u0443\u0442 \u0436\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0437\u0430\u0434\u0435\u043f\u043b\u043e\u0435\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0441\u0442\u0440\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e, \u2014 \u043c\u0435\u0447\u0442\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c \u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u043c: \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u043c \u0434\u0432\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430 \u043d\u0430 \u0431\u0430\u0437\u0435 minikube \u0438\u043b\u0438 Docker \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043a\u043e\u043c\u043c\u0438\u0447\u0435\u043d\u044b\u0445 \u0432 Git. \u0411\u044d\u043a\u0435\u043d\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0430 Go, \u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u2014 \u043d\u0430 Vue.js. \u0412\u0441\u0435 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u044f\u043c\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0447\u0442\u043e, \u043d\u0435\u0441\u043e\u043c\u043d\u0435\u043d\u043d\u043e, \u043f\u043e\u0432\u044b\u0441\u0438\u0442 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u041d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435 \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u0430 werf (\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/ru.werf.io\/documentation\/v1.2\/\"><u>\u043d\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0430\u0439\u0442\u0435<\/u><\/a>) \u2014 \u0441 \u0435\u0435 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0434\u0435\u043f\u043b\u043e\u0439 \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.  \u0412\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435.\u00a0<\/p>\n<blockquote>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/flant\/articles\/759040\/\"><u>\u0412 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/u><\/a> \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438, \u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b <a href=\"https:\/\/deckhouse.ru\/\">Deckhouse<\/a> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u044b <a href=\"https:\/\/ru.werf.io\/\">werf<\/a>. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430 \u043c\u044b \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0443\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e werf \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u0412\u0430\u043c \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043c\u044b \u0432\u0441\u0451 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u044b\u043b\u0430 \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0439.<\/p>\n<\/blockquote>\n<h2>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e <a href=\"https:\/\/github.com\/flant\/examples\/tree\/master\/2023\/08-deckhouse-werf\"><u>\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/u><\/a> \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041f\u043e\u043a\u0430 \u043e\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u043d\u044b\u0439 \u0431\u044d\u043a\u0435\u043d\u0434 \u043d\u0430 Go \u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0434\u0435\u043f\u043b\u043e\u044f \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 Kubernetes Helm-\u0447\u0430\u0440\u0442\u0430\u043c\u0438. \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043a\u0430\u043a \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f HTML-\u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u0438\u0445 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c \u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0442 \u0436\u0435\u0441\u0442\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u044d\u043a\u0435\u043d\u0434 \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0440\u0430\u0437\u0431\u0438\u0432 \u0435\u0433\u043e \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430: \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432\u0435\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434, \u0430 \u0432 \u0431\u044d\u043a\u0435\u043d\u0434\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043d\u0430 REST-\u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0447\u0430\u0440\u0442\u044b \u0434\u043b\u044f \u043d\u043e\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Docker Compose \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0431\u043e\u043b\u0435\u0435 \u00ab\u0441\u043b\u043e\u0436\u043d\u044b\u043c\u00bb \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u2014 \u0432\u0435\u0434\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0438 \u0431\u044d\u043a\u0435\u043d\u0434 \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u0438\u043c\u0435\u043d\u0438. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043d\u0430\u0448\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u043e\u0439 \u043a \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0436\u0438\u0437\u043d\u0438.\u00a0<\/p>\n<h3>\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 <a href=\"https:\/\/github.com\/flant\/examples\/tree\/master\/2023\/08-deckhouse-werf\"><u>\u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/u><\/a> \u0432 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>backend<\/code> \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0412 \u043d\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0411\u0414 \u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e REST\u00a0API.\u00a0<\/p>\n<p>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0441\u044f \u0432 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>frontend<\/code> \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430, \u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u043a\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e: \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u043d\u0430 \u0441\u0442\u0430\u0434\u0438\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 Vue.js.\u00a0<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:<\/p>\n<pre><code class=\"bash\">$ tree -a . . \u2514\u2500\u2500 backend    \u251c\u2500\u2500 .helm    \u2502   \u2514\u2500\u2500 templates    \u2502       \u251c\u2500\u2500 database.yaml    \u2502       \u251c\u2500\u2500 deployment.yaml    \u2502       \u251c\u2500\u2500 ingress.yaml    \u2502       \u251c\u2500\u2500 job-db-setup-and-migrate.yaml    \u2502       \u2514\u2500\u2500 service.yaml    \u251c\u2500\u2500 Dockerfile    \u251c\u2500\u2500 cmd    \u2502   \u2514\u2500\u2500 main.go    \u251c\u2500\u2500 db    \u2502   \u2514\u2500\u2500 migrations    \u2502       \u251c\u2500\u2500 000001_create_talkers_table.down.sql    \u2502       \u2514\u2500\u2500 000001_create_talkers_table.up.sql    \u251c\u2500\u2500 go.mod    \u251c\u2500\u2500 go.sum    \u251c\u2500\u2500 internal    \u2502   \u251c\u2500\u2500 app    \u2502   \u2502   \u2514\u2500\u2500 app.go    \u2502   \u251c\u2500\u2500 common    \u2502   \u2502   \u2514\u2500\u2500 json_logger_filter.go    \u2502   \u251c\u2500\u2500 controllers    \u2502   \u2502   \u2514\u2500\u2500 db_controllers.go    \u2502   \u2514\u2500\u2500 services    \u2502       \u2514\u2500\u2500 db_service.go    \u251c\u2500\u2500 templates    \u2502   \u251c\u2500\u2500 index.html    \u2502   \u251c\u2500\u2500 remember.html    \u2502   \u2514\u2500\u2500 say.html    \u2514\u2500\u2500 werf.yaml <\/code><\/pre>\n<h3>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0412 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430 \u0432\u0435\u0431-\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 Vue.js, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0432\u0441\u0435, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432, \u0430 \u043e\u0442\u0432\u0435\u0442\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435 \u0432 HTML, \u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON \u2014 \u043a\u0430\u043a \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b \ud83d\ude42<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0434\u0430\u043b\u0438\u043c \u0432 \u0444\u0430\u0439\u043b\u0435 <code>internal\/app\/app.go<\/code> \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442 <code>\/<\/code>, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430 \u043d\u0435\u0433\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434. \u041a \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u043e\u0442\u0430\u043c <code>remember<\/code> \u0438 <code>say<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0438\u0437 \u0411\u0414, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0434\u043f\u0443\u0442\u044c <code>\/api<\/code> (\u0434\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a: <code>remember\/api<\/code>, <code>say\/api<\/code>), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u043e \u043d\u0443\u0436\u043d\u044b\u043c \u043f\u0443\u0442\u044f\u043c \u043f\u0440\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u0438 Docker Compose \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"go\">func Run() { route := gin.New() route.Use(gin.Recovery()) route.Use(common.JsonLogger())   route.GET(\"\/api\/remember\", controllers.RememberController) route.GET(\"\/api\/say\", controllers.SayController)   err := route.Run() if err != nil { return } }<\/code><\/pre>\n<blockquote>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong><\/p>\n<p>\u041b\u0443\u0447\u0448\u0435 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0434\u0443\u043c\u0430\u0442\u044c, \u043a\u0430\u043a \u0431\u0443\u0434\u0443\u0442 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0430\u044f \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u0440\u0430\u0437\u0443 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c API. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043c\u0430\u0436\u043e\u0440\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0441\u0435 \u043d\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b API \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u043e \u043f\u0443\u0442\u0438 \/api\/v2, \u0430 \u0441\u0442\u0430\u0440\u044b\u0435 \u043e\u0441\u0442\u0430\u043d\u0443\u0442\u0441\u044f \u043d\u0430 \/api\/v1.<\/p>\n<\/blockquote>\n<p>\u0417\u0430\u043c\u0435\u043d\u0438\u043c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u0445 \u0442\u0438\u043f \u043e\u0442\u0432\u0435\u0442\u0430 \u0441 HTML \u043d\u0430 JSON, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0432 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u043e\u043c \u0432\u0438\u0434\u0435.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>internal\/controllers\/db_controllers.go<\/code>:<\/p>\n<pre><code class=\"go\">func RememberController(c *gin.Context) { dbType, dbPath := services.GetDBCredentials()   db, err := sql.Open(dbType, dbPath) if err != nil { panic(err) }   message := c.Query(\"message\") name := c.Query(\"name\")   _, err = db.Exec(\"INSERT INTO talkers (message, name) VALUES (?, ?)\", message, name) if err != nil { panic(err) }   c.JSON(http.StatusOK, gin.H{ \"Name\":    name, \"Message\": message, })   defer db.Close() }<\/code><\/pre>\n<p>\u0412 \u043d\u0435\u043c \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043a\u0430\u043a \u043f\u0440\u0435\u0436\u0434\u0435: \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0444\u043e\u0440\u043c\u044b \u043d\u0430 \u0441\u0430\u0439\u0442\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0443, \u0438 \u0438\u0445 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0432 \u0411\u0414. \u0418\u0437\u043c\u0435\u043d\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0432\u0435\u0442 \u0441 \u0432\u044b\u0437\u043e\u0432\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 HTML \u043d\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e JSON (\u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430, \u0435\u0441\u043b\u0438 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u043d\u0438\u0437\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 <code>c.JSON<\/code>).<\/p>\n<p>\u041a\u043e\u0434 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0411\u0414 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u0432 \u0442\u043e\u043c \u0436\u0435 \u0444\u0430\u0439\u043b\u0435 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"go\">func SayController(c *gin.Context) { dbType, dbPath := services.GetDBCredentials()   db, err := sql.Open(dbType, dbPath) if err != nil { panic(err) }   result, err := db.Query(\"SELECT * FROM talkers\") if err != nil { panic(err) }   count := 0 var data []map[string]string   for result.Next() { count++ var id int var message string var name string   err = result.Scan(&amp;id, &amp;message, &amp;name) if err != nil { panic(err) }   data = append(data, map[string]string{ \"Name\":    name, \"Message\": message}) } if count == 0 { c.JSON(http.StatusOK, gin.H{ \"Error\": \"There are no messages from talkers!\", }) } else { c.JSON(http.StatusOK, gin.H{ \"Messages\": data, }) } }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0441\u0435 \u0442\u0430\u043a\u0436\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u2014 \u043c\u044b \u043b\u0438\u0448\u044c \u0437\u0430\u043c\u0435\u043d\u0438\u043b\u0438 HTML \u043d\u0430 JSON (\u0434\u0432\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0431\u043b\u043e\u043a\u0430 \u043a\u043e\u0434\u0430, \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0441 <code>c.JSON<\/code>).<\/p>\n<p>\u0423\u0440\u0430! \u041e\u0442\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0435\u0440\u0435\u0439\u0434\u044f \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>backend<\/code> \u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435:<\/p>\n<pre><code class=\"bash\">werf converge --repo &lt;\u0418\u041c\u042f \u041f\u041e\u041b\u042c\u0417\u041e\u0412\u0410\u0422\u0415\u041b\u042f DOCKER HUB>\/habr-app<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0443 \/<code>say<\/code> \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0411\u0414 \u0432 \u0432\u0438\u0434\u0435 JSON-\u0444\u0430\u0439\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"bash\">$ curl https:\/\/habrapp.example.com\/say | jq  {   \"Messages\": [     {       \"Message\": \"\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!\",       \"Name\": \"Zhbert\"     }   ] }<\/code><\/pre>\n<blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0441 \u044d\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430, \u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u2014 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u0432\u0435\u0440\u043d\u0435\u0442\u0441\u044f JSON, \u043d\u043e \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0443\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u044d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u043d\u0435 \u043f\u0443\u0433\u0430\u0439\u0442\u0435\u0441\u044c.<\/p>\n<\/blockquote>\n<p>\u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0443\u0434\u0430\u043b\u0438\u043b\u0438 \u0438\u0437 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 <code>\/<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f 404-\u044f \u043e\u0448\u0438\u0431\u043a\u0430, \u043a\u0430\u043a \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435:<\/p>\n<pre><code class=\"bash\">$ curl https:\/\/habrapp.example.com  404 page not found<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043c\u044b \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c, \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 <code>backend<\/code> \u0444\u0430\u0439\u043b <code>werf.yaml<\/code> \u043d\u0430 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0432\u044b\u0448\u0435 \u2014 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u0441\u0440\u0430\u0437\u0443 \u0434\u0432\u0443\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0433\u043e.<\/p>\n<p>\u041d\u0443 \u0447\u0442\u043e \u0436, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430.<\/p>\n<h3>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Vue.js, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430: \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0431\u044d\u043a\u0435\u043d\u0434\u0430.<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 <a href=\"https:\/\/cli.vuejs.org\/ru\/guide\/creating-a-project.html\"><u>Vue CLI<\/u><\/a> \u043d\u0430 \u0432\u0430\u0448\u0443 \u043c\u0430\u0448\u0438\u043d\u0443. \u041b\u0443\u0447\u0448\u0435 \u0441\u0440\u0430\u0437\u0443 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/docs.npmjs.com\/about-npm\"><u>npm<\/u><\/a>, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043e\u043d \u043d\u0430\u043c \u0435\u0449\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u043e\u0435 Vue-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">vue create frontend<\/code><\/pre>\n<blockquote>\n<p>\u0422\u0430\u043a\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 <a href=\"https:\/\/cli.vuejs.org\/ru\/guide\/creating-a-project.html\">\u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c<\/a>, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/vuejs\/create-vue\">create-vue<\/a> \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u0430\u0440\u043a\u0430\u0441\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<\/blockquote>\n<p>\u0412 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p>\n<pre><code class=\"bash\">> Default ([Vue 3] babel, eslint<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0437\u0430\u0439\u043c\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u044f\u0442\u0441\u044f \u0441\u0442\u0430\u0442\u0443\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"bash\">Vue CLI v5.0.8 \u2728  Creating project in \/Users\/zhbert\/Programming\/habr-werf-local-stend\/frontend. \u2699\ufe0f  Installing CLI plugins. This might take a while...  added 862 packages, and audited 863 packages in 24s  packages are looking for funding   run `npm fund` for details  found 0 vulnerabilities ?  Invoking generators... ?  Installing additional dependencies...  added 101 packages, and audited 964 packages in 3s  packages are looking for funding   run `npm fund` for details  found 0 vulnerabilities \u2693  Running completion hooks...  ?  Generating README.md...  ?  Successfully created project frontend. ?  Get started with the following commands:   $ cd frontend  $ npm run serve<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u043c\u0443 \u0441\u043e\u0432\u0435\u0442\u0443 \u0432 \u0441\u0430\u043c\u043e\u043c \u043a\u043e\u043d\u0446\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"bash\">npm run serve  > frontend@0.1.0 serve > vue-cli-service serve   INFO  Starting development server...    <\/code><\/pre>\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-359234","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/359234","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=359234"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/359234\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=359234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=359234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=359234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}