Inventos ã® Alexander Sigachev ã«ããã¬ããŒããDocker + Gitlab CI ã䜿çšããéçºãšãã¹ãã®ããã»ã¹ãã®ãã©ã³ã¹ã¯ãªãããèªãããšãææ¡ããŸãã
Docker + Gitlab CI ã«åºã¥ããéçºããã³ãã¹ã ããã»ã¹ã®å®è£ ãå§ããã°ããã®äººã¯ãåºæ¬çãªè³ªåãããããšããããããŸãã ã©ãããå§ããã°ããã§ãããã? ã©ã®ããã«æŽçããã°ããã§ããããïŒ ãã¹ãæ¹æ³ã¯?
ãã®ã¬ããŒãã¯ãDocker ãš Gitlab CI ã䜿çšããéçºãšãã¹ãã®ããã»ã¹ã«ã€ããŠæ§é åãããæ¹æ³ã§èª¬æãããŠãããããåªããŠããŸãã ãã®ã¬ããŒãèªäœã¯ 2017 幎ã®ãã®ã§ãã ãã®ã¬ããŒããããåºæ¬ãæ¹æ³è«ãèãæ¹ã䜿çšçµéšãåŠã¶ããšãã§ãããšæããŸãã
æ°ã«ããªã人ã¯ç«ã®äžã«ããŠãã ããã
ç§ã®ååã¯ã¢ã¬ã¯ãµã³ããŒã»ã·ã¬ãã§ãã§ãã ç§ã¯ã€ã³ãã³ãã¹ã§åããŠããŸãã Docker ã䜿çšããç§ã®çµéšãšã瀟å ã®ãããžã§ã¯ãã« Docker ãåŸã ã«å°å ¥ããŠããæ¹æ³ã«ã€ããŠã話ããŸãã
ãã¬ãŒã³ããŒã·ã§ã³ã®ãããã¯: Docker ãš Gitlab CI ã䜿çšããéçºããã»ã¹ã
ãã㯠Docker ã«ã€ããŠã® 2 åç®ã®è©±ã§ãã æåã®ã¬ããŒãã®æç¹ã§ã¯ãéçºè
ã®ãã·ã³äžã§ã®ã¿ Docker in Development ã䜿çšããŠããŸããã Dockerã䜿ã£ãŠãã瀟å¡ã®æ°ã¯3ïœXNUMX人çšåºŠã§ããã åŸã
ã«çµéšãç©ãã§ãå°ããã€åé²ããŠããŸããã ç§ãã¡ã®ãžã®ãªã³ã¯
ãã®ã¬ããŒãã«ã¯äœãèšèŒãããã®ã§ãããã? ç§ãã¡ãéããçæãã解決ããåé¡ã«ã€ããŠã®çµéšãå ±æããŸãã ã©ããçŸããããã§ã¯ãããŸããã§ããããå ã«é²ãããšãã§ããŸããã
ç§ãã¡ã®ã¢ãããŒã¯ãæã«å ¥ããã®ã¯ãã¹ãŠãããã³ã°ããããšã§ãã
ç§ãã¡ã¯ã©ã®ãããªåé¡ã解決ããŠããã®ã§ãããã?
瀟å ã«è€æ°ã®ããŒã ãããå Žåãããã°ã©ããŒã¯å ±æãªãœãŒã¹ãšãªããŸãã ããã°ã©ããŒããããããžã§ã¯ãããåŒãæããããã°ããã®éå¥ã®ãããžã§ã¯ãã«ä»»ããã段éããããŸãã
ããã°ã©ããŒãããã«ç解ã§ããããã«ããã«ã¯ããããžã§ã¯ãã®ãœãŒã¹ ã³ãŒããããŠã³ããŒãããŠãã§ããã ãæ©ãç°å¢ãèµ·åããå¿ èŠããããŸããããã«ããããã®ãããžã§ã¯ãã®åé¡ã®è§£æ±ºãããã«é²ããããšãã§ããŸãã
éåžžããŒãããå§ããå Žåããããžã§ã¯ãã«ã¯ã»ãšãã©ããã¥ã¡ã³ãããããŸããã èšå®æ¹æ³ã«é¢ããæ å ±ã¯å€åã®æ¹ã®ã¿ã«å ¬éãããŠããŸãã åŸæ¥å¡ã¯ XNUMX ïœ XNUMX æ¥ã§èªåãã¡ã§è·å Žãèšå¶ããŸãã ãããé«éåããããã«ãDocker ã䜿çšããŸããã
次ã®çç±ã¯ãéçºã«ãããèšå®ã®æšæºåã§ãã ç§ã®çµéšã§ã¯ãéçºè ã¯åžžã«äž»å°æš©ãæ¡ããŸãã XNUMX 件ããšã«ãã«ã¹ã¿ã ãã¡ã€ã³ (vasya.dev ãªã©) ãå ¥åãããŸãã 圌ã®é£ã«åº§ã£ãŠããã®ã¯é£äººã® Petya ã§ããã®ãã¡ã€ã³ã¯ petya.dev ã§ãã ãã®ãã¡ã€ã³åã䜿çšããŠãWeb ãµã€ããŸãã¯ã·ã¹ãã ã®ã³ã³ããŒãã³ããéçºããŸãã
ã·ã¹ãã ãæé·ãããããã®ãã¡ã€ã³åãæ§æã«çµã¿èŸŒãŸãå§ãããšãéçºç°å¢ã®ç«¶åãçºçãããµã€ã ãã¹ãæžãæããããŸãã
ããŒã¿ããŒã¹èšå®ã§ãåãããšãèµ·ãããŸãã ã»ãã¥ãªãã£ãæ°ã«ããã空㮠root ãã¹ã¯ãŒãã䜿çšããŠäœæ¥ãã人ãããŸãã ã€ã³ã¹ããŒã«æ®µéã§ãMySQL ã¯èª°ãã«ãã¹ã¯ãŒããèŠæ±ãããã®ãã¹ã¯ãŒã㯠123 ã§ããããšãå€æããŸãããéçºè
ã®ã³ââãããã«å¿ããŠããŒã¿ããŒã¹æ§æãåžžã«å€æŽãããããšããããããŸãã 誰ããèšå®ãä¿®æ£ããŸãããã誰ããèšå®ãä¿®æ£ããŸããã§ããã ããçš®ã®ãã¹ãæ§æãåãåºãããšãã«ããªãã¯ããããŸããã .gitignore
ãããŠåéçºè
ã¯ããŒã¿ããŒã¹ãã€ã³ã¹ããŒã«ããå¿
èŠããããŸããã ãã®ãããå§ããã®ãé£ãããªããŸããã ãšããããããŒã¿ããŒã¹ã«ã€ããŠèŠããŠããå¿
èŠããããŸãã ããŒã¿ããŒã¹ã®åæåããã¹ã¯ãŒãã®å
¥åããŠãŒã¶ãŒã®ç»é²ãããŒãã«ã®äœæãªã©ãå¿
èŠã§ãã
ãã 2017 ã€ã®åé¡ã¯ãã©ã€ãã©ãªã®ããŒãžã§ã³ãç°ãªãããšã§ãã éçºè ãããŸããŸãªãããžã§ã¯ãã«åãçµãããšããããããŸãã 5.5 幎å (5.7 幎ãã - 線泚) ããå§ãŸã£ãã¬ã¬ã·ãŒãããžã§ã¯ãããããŸãã ç«ã¡äžãæã«ã¯ãMySQL 2017 ããéå§ããŸããã MySQL ã®ããæ°ããããŒãžã§ã³ãããšãã° XNUMX 以å (XNUMX 幎 - 線泚) ãå®è£ ããããšããææ°ã®ãããžã§ã¯ãããããŸãã
MySQL ãæ±ã人ãªã誰ã§ãããããã®ã©ã€ãã©ãªã«ã¯äŸåé¢ä¿ã䌎ãããšãç¥ã£ãŠããŸãã ïŒå¡ã䜵走ããã®ã¯ããªãåé¡ãããã å°ãªããšããå€ãã¯ã©ã€ã¢ã³ããæ°ããããŒã¿ããŒã¹ã«æ¥ç¶ããã«ã¯åé¡ããããŸãã ããã«ãããããã€ãã®åé¡ãçºçããŸãã
次ã®åé¡ã¯ãéçºè ãããŒã«ã« ãã·ã³ã§äœæ¥ããå ŽåãããŒã«ã« ãªãœãŒã¹ãããŒã«ã« ãã¡ã€ã«ãããŒã«ã« RAM ã䜿çšããããšã§ãã åé¡ã«å¯Ÿãããœãªã¥ãŒã·ã§ã³ãéçºããéã®ãã¹ãŠã®å¯Ÿè©±ã¯ã3 å°ã®ãã·ã³äžã§åäœãããšãããã¬ãŒã ã¯ãŒã¯å ã§å®è¡ãããŸãã äŸãšããŠã¯ãProduction 3 ã«ããã¯ãšã³ã ãµãŒããŒããããéçºè ããã¡ã€ã«ãã«ãŒã ãã£ã¬ã¯ããªã«ä¿åãããããã nginx ããã¡ã€ã«ãååŸããŠãªã¯ãšã¹ãã«å¿çããå Žåã§ãã ãã®ãããªã³ãŒããéçšç°å¢ã«äŸµå ¥ãããšããã®ãã¡ã€ã«ã XNUMX ã€ã®ãµãŒããŒã®ããããã«ååšããããšãããããŸãã
ãã€ã¯ããµãŒãã¹ã®æ¹åæ§ã¯çŸåšçºå±ãã€ã€ãããŸãã 倧èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ããçžäºã«å¯Ÿè©±ããããã€ãã®å°ããªã³ã³ããŒãã³ãã«åå²ããå Žåã ããã«ãããç¹å®ã®ã¿ã¹ã¯ã®ã¹ã¿ãã¯ã«å¯ŸããŠãã¯ãããžãéžæã§ããããã«ãªããŸãã ãŸããéçºè éã§äœæ¥ãšè²¬ä»»ãå ±æããããšãã§ããŸãã
ããã³ããšã³ãéçºè 㯠JS äžã§éçºããŠãããããã¯ãšã³ãã«ã¯ã»ãšãã©åœ±é¿ãäžããŸããã ããã¯ãšã³ãéçºè ã¯ããã®å ŽåãRuby on Rails ãéçºããFrondend ã«ã¯å¹²æžããŸããã ã€ã³ã¿ã©ã¯ã·ã§ã³ã¯ API ã䜿çšããŠå®è¡ãããŸãã
ããŸãã«ãDocker ã®å©ããåããŠãã¹ããŒãžã³ã°ã§ãªãœãŒã¹ããªãµã€ã¯ã«ããããšãã§ããŸããã åãããžã§ã¯ãã«ã¯ãã®ç¹æ§ããããããç¹å®ã®èšå®ãå¿ èŠã§ããã ç©ççã«ã¯ãä»®æ³ãµãŒããŒãå²ãåœãŠãŠåå¥ã«æ§æããããããçš®ã®å¯å€ç°å¢ãå ±æããå¿ èŠããããã©ã€ãã©ãªã®ããŒãžã§ã³ã«ãã£ãŠã¯ãããžã§ã¯ããçžäºã«åœ±é¿ãäžããå¯èœæ§ããããŸããã
ããŒã«ã äœã䜿ãã®ã§ããããïŒ
- ããã«ãŒèªäœã Dockerfile ã¯ãåäžã¢ããªã±ãŒã·ã§ã³ã®äŸåé¢ä¿ãèšè¿°ããŸãã
- Docker-compose ã¯ãããã€ãã® Docker ã¢ããªã±ãŒã·ã§ã³ããŸãšãããã³ãã«ã§ãã
- ãœãŒã¹ã³ãŒãã®ä¿åã«ã¯ GitLab ã䜿çšããŸãã
- ã·ã¹ãã çµ±åã«ã¯GitLab-CIãå©çšããŠããŸãã
ã¬ããŒã㯠XNUMX ã€ã®éšåããæ§æãããŸãã
æåã®éšåã§ã¯ãéçºè ã®ãã·ã³äžã§ Docker ãã©ã®ããã«å®è¡ããããã«ã€ããŠèª¬æããŸãã
XNUMX çªç®ã®ããŒãã§ã¯ãGitLab ãšå¯Ÿè©±ããæ¹æ³ããã¹ããå®è¡ããæ¹æ³ãã¹ããŒãžã³ã°ã«å±éããæ¹æ³ã«ã€ããŠèª¬æããŸãã
Docker ã¯ã(宣èšçã¢ãããŒãã䜿çšããŠ) å¿
èŠãªã³ã³ããŒãã³ããèšè¿°ããããšãå¯èœã«ãããã¯ãããžãŒã§ãã ãã㯠Dockerfile ã®äŸã§ãã ããã§ãå
¬åŒã® Ruby:2.3.0 Docker ã€ã¡ãŒãžããç¶æ¿ããŠããããšã宣èšããŸãã Ruby ããŒãžã§ã³ 2.3 ãã€ã³ã¹ããŒã«ãããŠããŸãã å¿
èŠãªãã«ã ã©ã€ãã©ãªãš NodeJS ãã€ã³ã¹ããŒã«ããŸãã ãã£ã¬ã¯ããªãäœæããããšã説æããŸã /app
ã ã¢ããªãã£ã¬ã¯ããªãäœæ¥ãã£ã¬ã¯ããªãšããŠèšå®ããŸãã ãã®ãã£ã¬ã¯ããªã«ãå¿
èŠãªæå°éã® Gemfile ãš Gemfile.lock ãé
眮ããŸãã 次ã«ããã®äŸåé¢ä¿ã€ã¡ãŒãžãã€ã³ã¹ããŒã«ãããããžã§ã¯ãããã«ãããŸãã ã³ã³ãããŒãå€éšããŒã 3000 ã§ãªãã¹ã³ããæºåãã§ããŠããããšã瀺ããŸããæåŸã®ã³ãã³ãã¯ãã¢ããªã±ãŒã·ã§ã³ãçŽæ¥èµ·åããã³ãã³ãã§ãã ãããžã§ã¯ãéå§ã³ãã³ããå®è¡ãããšãã¢ããªã±ãŒã·ã§ã³ã¯æå®ãããã³ãã³ããå®è¡ããããšããŸãã
ããã¯ãdocker-compose ãã¡ã€ã«ã®æå°éã®äŸã§ãã ãã®å ŽåãXNUMX ã€ã®ã³ã³ãããŒéã«æ¥ç¶ãããããšã瀺ããŸãã ããã¯ããŒã¿ããŒã¹ ãµãŒãã¹ãš Web ãµãŒãã¹ã«çŽæ¥åæ ãããŸãã ã»ãšãã©ã®å ŽåãWeb ã¢ããªã±ãŒã·ã§ã³ã¯ããŒã¿ãä¿åããããã®ããã¯ãšã³ããšããŠäœããã®ããŒã¿ããŒã¹ãå¿ èŠãšããŸãã ããã§ã¯ MySQL ã䜿çšããŠãããããäŸã¯ MySQL ã䜿çšããŠããŸãããä»ã®ããŒã¿ããŒã¹ (PostgreSQLãRedis) ã䜿çšããããšã劚ãããã®ã¯ãããŸããã
Docker ããã®å ¬åŒãœãŒã¹ãã MySQL 5.7.14 ã®ã€ã¡ãŒãžãå€æŽããã«ååŸããŸãã Web ã¢ããªã±ãŒã·ã§ã³ãæ åœããã€ã¡ãŒãžãçŸåšã®ãã£ã¬ã¯ããªããåéããŸãã æåã®èµ·åæã«ç»åãåéããŸãã 次ã«ãããã§å®è¡ããŠããã³ãã³ããå®è¡ãããŸãã æ»ããšãPuma çµç±ã®èµ·åã³ãã³ããå®çŸ©ãããŠããããšãããããŸãã Puma 㯠Ruby ã§æžããããµãŒãã¹ã§ãã XNUMX çªç®ã®ã±ãŒã¹ã§ã¯ããªãŒããŒã©ã€ãããŸãã ãã®ã³ãã³ãã¯ãããŒãºãã¿ã¹ã¯ã«å¿ããŠä»»æã«äœ¿çšã§ããŸãã
ãŸããéçºè ãã¹ã ãã·ã³ã®ããŒããã³ã³ãã ããŒãã® 3000 ãã 3000 ã«è»¢éããå¿ èŠãããããšã«ã€ããŠã説æããŸãã ããã¯ãDocker ã«çŽæ¥çµã¿èŸŒãŸããŠãã iptables ãšãã®ã¡ã«ããºã ã䜿çšããŠèªåçã«è¡ãããŸãã
éçºè ã¯ã以åãšåæ§ã«ãå©çšå¯èœãªä»»æã® IP ã¢ãã¬ã¹ã«ã¢ã¯ã»ã¹ããããšãã§ããŸããããšãã°ã127.0.0.1 ã¯ãã·ã³ã®ããŒã«ã«ãŸãã¯å€éš IP ã¢ãã¬ã¹ã§ãã
æåŸã®è¡ã¯ãWeb ã³ã³ããã DB ã³ã³ããã«äŸåããŠããããšã瀺ããŠããŸãã Web ã³ã³ããã®éå§ãåŒã³åºããšãdocker-compose ãæåã«ããŒã¿ããŒã¹ãéå§ããŸãã ããŒã¿ããŒã¹ã®éå§æã« (å®éã«ã¯ãã³ã³ãããŒã®èµ·ååŸã§ããããã¯ããŒã¿ããŒã¹ã®æºåãæŽã£ãŠããããšãä¿èšŒãããã®ã§ã¯ãããŸãã)ãããã¯ãšã³ãã§ããã¢ããªã±ãŒã·ã§ã³ãèµ·åããŸãã
ããã«ãããããŒã¿ããŒã¹ãèµ·åããŠããªããšãã®ãšã©ãŒãåé¿ãããããŒã¿ããŒã¹ ã³ã³ãããŒãåæ¢ãããšãã«ãªãœãŒã¹ãç¯çŽãããä»ã®ãããžã§ã¯ãã«ãªãœãŒã¹ã解æŸãããŸãã
ãããžã§ã¯ãã§ããŒã¿ããŒã¹ Dockerization ã䜿çšã§ããããã«ãªã£ãçç±ã ãã¹ãŠã®éçºè åãã« MySQL ã®ããŒãžã§ã³ãä¿®æ£ããŸãã ããã«ãããããŒãžã§ã³ãç°ãªãå Žåãæ§æãæ§æãããã©ã«ãèšå®ãå€æŽãããå Žåã«çºçããå¯èœæ§ã®ãããšã©ãŒãåé¿ãããŸãã ããã«ãããããŒã¿ããŒã¹ããã°ã€ã³ããã¹ã¯ãŒãã«å ±éã®ãã¹ãåãæå®ã§ããŸãã ç§ãã¡ã¯ã以åã®ããã«æ§æãã¡ã€ã«å ã®ååãšç«¶åã®åç©åããè±åŽãã€ã€ãããŸãã
éçºç°å¢ã«ã¯ãããã©ã«ããšã¯ç°ãªããããæé©ãªæ§æã䜿çšããæ©äŒããããŸãã MySQL ã¯ããã©ã«ãã§åŒ±ããã·ã³åãã«æ§æãããŠããããã®ãŸãŸã®ç¶æ ã§ã¯ããã©ãŒãã³ã¹ãéåžžã«æªãã§ãã
Docker ã䜿çšãããšãå¿ èŠãªããŒãžã§ã³ã® PythonãRubyãNodeJSãPHP ã€ã³ã¿ãŒããªã¿ãŒã䜿çšã§ããŸãã ããçš®ã®ããŒãžã§ã³ ãããŒãžã£ãŒã䜿çšããå¿ èŠããªããªããŸãã 以åã® Ruby ã§ã¯ããããžã§ã¯ãã«å¿ããŠããŒãžã§ã³ãå€æŽã§ãã rpm ããã±ãŒãžã䜿çšãããŠããŸããã ãŸããDocker ã³ã³ãããŒã®ãããã§ãã³ãŒããã¹ã ãŒãºã«ç§»è¡ããäŸåé¢ä¿ãšãšãã«ããŒãžã§ã³ç®¡çããããšãã§ããŸãã ã€ã³ã¿ããªã¿ãšã³ãŒãã®äž¡æ¹ã®ããŒãžã§ã³ãåé¡ãªãç解ã§ããŸãã ããŒãžã§ã³ãæŽæ°ããã«ã¯ãå€ãã³ã³ãããäžããæ°ããã³ã³ãããäžããŸãã äœãåé¡ãçºçããå Žåã¯ãæ°ããã³ã³ãããäžããå€ãã³ã³ãããæã¡äžããããšãã§ããŸãã
ã€ã¡ãŒãžããã«ããããšãéçºç°å¢ãšéçšç°å¢ã®äž¡æ¹ã®ã³ã³ãããŒãåãã«ãªããŸãã ããã¯ç¹ã«å€§èŠæš¡ãªã€ã³ã¹ããŒã«ã«åœãŠã¯ãŸããŸãã
ããã³ããšã³ãã§ã¯ JavaScipt ãš NodeJS ã䜿çšããŸãã
ããã§ãReacJS äžã®æåŸã®ãããžã§ã¯ããå®æããŸããã éçºè ã¯ã³ã³ããå ã®ãã¹ãŠãå®è¡ããããããªããŒãã䜿çšããŠéçºããŸããã
次ã«ãJavaScipt ã¢ã»ã³ã㪠ã¿ã¹ã¯ãèµ·åãããéçã«ã³ã³ãã€ã«ãããã³ãŒãã nginx ã®ä¿åãªãœãŒã¹ãéããŠæäŸãããŸãã
ããã§ç§ãã¡ã®ååã®ãããžã§ã¯ãã®ã¹ããŒã ã瀺ããŸããã
ã©ã®ãããªã¿ã¹ã¯ã解決ãããŸããã? ã¢ãã€ã«ããã€ã¹ãé£æºããã·ã¹ãã ãæ§ç¯ããå¿ èŠããããŸããã 圌ãã¯ããŒã¿ãåãåããŸãã XNUMX ã€ã®å¯èœæ§ã¯ããã®ããã€ã¹ã«ããã·ã¥éç¥ãéä¿¡ããããšã§ãã
ãã®ããã«ç§ãã¡ã¯äœãããŸãããïŒ
ç§ãã¡ã¯ãJS äžã®ç®¡çéšåãRuby on Rails ã® REST ã€ã³ã¿ãŒãã§ãŒã¹ãä»ããŠåäœããããã¯ãšã³ããªã©ã®ã³ã³ããŒãã³ãã«ã¢ããªã±ãŒã·ã§ã³ãåå²ããŸããã ããã¯ãšã³ãã¯ããŒã¿ããŒã¹ãšå¯Ÿè©±ããŸãã çæãããçµæã¯ã¯ã©ã€ã¢ã³ãã«æž¡ãããŸãã 管çããã«ã¯ãREST ã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠããã¯ãšã³ãããã³ããŒã¿ããŒã¹ãšå¯Ÿè©±ããŸãã
ããã·ã¥éç¥ãéä¿¡ããå¿ èŠããããŸããã ãã®åã«ã¯ãã¢ãã€ã« ãã©ãããã©ãŒã ã«éç¥ãé ä¿¡ããã¡ã«ããºã ãå®è£ ãããããžã§ã¯ãããããŸããã
ç§ãã¡ã¯æ¬¡ã®ã¹ããŒã ãéçºããŸããããã©ãŠã¶ãŒããã®ãªãã¬ãŒã¿ãŒã管çããã«ãšå¯Ÿè©±ãã管çããã«ãããã¯ãšã³ããšå¯Ÿè©±ããã¿ã¹ã¯ã¯ããã·ã¥éç¥ãéä¿¡ããããšã§ãã
ããã·ã¥éç¥ã¯ãNodeJS ã«å®è£ ãããŠããå¥ã®ã³ã³ããŒãã³ããšå¯Ÿè©±ããŸãã
ãã¥ãŒãæ§ç¯ããããã®ã¡ã«ããºã ã«åŸã£ãŠéç¥ãéä¿¡ãããŸãã
ããã§ã¯ 2 ã€ã®ããŒã¿ããŒã¹ãæãããŠããŸãã çŸæç¹ã§ã¯ãDocker ã®å©ããåããŠãäºãã«ãŸã£ããé¢é£æ§ã®ãªã XNUMX ã€ã®ç¬ç«ããããŒã¿ããŒã¹ã䜿çšããŠããŸãã ããã«ãå ±éã®ä»®æ³ãããã¯ãŒã¯ããããç©çããŒã¿ã¯éçºè ã®ãã·ã³äžã®ç°ãªããã£ã¬ã¯ããªã«ä¿åãããŸãã
åãã§ãããæ°å€çã«ã¯åãã§ãã ããã§ã³ãŒãã®åå©çšãéèŠã«ãªããŸãã
å ã»ã©ã©ã€ãã©ãªã®åœ¢åŒã§ã³ãŒããåå©çšããããšã«ã€ããŠèª¬æããŸãããããã®äŸã§ã¯ãããã·ã¥éç¥ã«å¿çãããµãŒãã¹ãå®å šãªãµãŒããŒãšããŠåå©çšãããŸãã API ãæäŸããŸãã ãããŠãç§ãã¡ã®æ°ããéçºã¯ãã§ã«ãããšçžäºäœçšããŠããŸãã
åœæãNodeJS ã®ããŒãžã§ã³ 4 ã䜿çšããŠããŸããã çŸåš (2017 幎 - 線泚)ãæè¿ã®éçºã§ã¯ NodeJS ã®ããŒãžã§ã³ 7 ã䜿çšããŠããŸãã æ°ããã³ã³ããŒãã³ãã«æ°ããããŒãžã§ã³ã®ã©ã€ãã©ãªãå«ãŸããŠãåé¡ã¯ãããŸããã
å¿ èŠã«å¿ããŠãããã·ã¥éç¥ãµãŒãã¹ãããªãã¡ã¯ã¿ãªã³ã°ã㊠NodeJS ããŒãžã§ã³ãäžããããšãã§ããŸãã
ãŸããAPI ã®äºææ§ãç¶æã§ããã°ããããŸã§äœ¿çšããŠããä»ã®ãããžã§ã¯ãã«çœ®ãæããããšãå¯èœã«ãªããŸãã
Dockerãè¿œå ããã«ã¯äœãå¿ èŠã§ãã? å¿ èŠãªäŸåé¢ä¿ãèšè¿°ãã Dockerfile ããªããžããªã«è¿œå ããŸãã ãã®äŸã§ã¯ãã³ã³ããŒãã³ããè«ççã«åå²ãããŠããŸãã ããã¯ããã¯ãšã³ãéçºè ã®æå°ã»ããã§ãã
æ°ãããããžã§ã¯ããäœæãããšãã¯ãDockerfile ãäœæããç®çã®ãšã³ã·ã¹ãã (PythonãRubyãNodeJS) ãèšè¿°ããŸãã docker-compose ã§ã¯ãå¿ èŠãªäŸåé¢ä¿ã§ããããŒã¿ããŒã¹ã«ã€ããŠèª¬æããŸãã ç¹å®ã®ããŒãžã§ã³ã®ããŒã¿ããŒã¹ãå¿ èŠã§ããããã¡ãã¡ã«ããŒã¿ãä¿åããå¿ èŠããããšèª¬æããŸãã
éçãµãŒãã¹ãæäŸããããã«ãnginx ãåããå¥ã® XNUMX çªç®ã®ã³ã³ããã䜿çšããŸãã åçã®ã¢ããããŒããå¯èœã§ãã ããã¯ãšã³ãã¯ããããäºåã«æºåãããããªã¥ãŒã ã«é 眮ããŸãããã®ããªã¥ãŒã ã nginx ã䜿çšããŠã³ã³ãããŒã«ããŠã³ããããéçã«ãªããŸãã
nginxãmysql æ§æãä¿åããããã«ãå¿ èŠãªæ§æãä¿åãã Docker ãã©ã«ããŒãè¿œå ããŸããã éçºè ãèªåã®ãã·ã³äžã§ãªããžããªã® git clone ãå®è¡ãããšãããŒã«ã«éçºã®æºåãã§ãããããžã§ã¯ãããã§ã«å®æããŠããŸãã ã©ã®ããŒããã©ã®èšå®ãé©çšãããã¯åé¡ãããŸããã
次ã«ã管çãéç¥ APIãããã·ã¥éç¥ãšããããã€ãã®ã³ã³ããŒãã³ãããããŸãã
ããããã¹ãŠãéå§ããããã«ãdockerized-app ãšåŒã°ããå¥ã®ãªããžããªãäœæããŸããã çŸæç¹ã§ã¯ãåã³ã³ããŒãã³ãã®åã«è€æ°ã®ãªããžããªã䜿çšããŠããŸãã ãããã¯è«ççã«ç°ãªãã ãã§ããGitLab ã§ã¯ãã©ã«ããŒã®ããã«èŠããŸãããéçºè ã®ãã·ã³ã§ã¯ç¹å®ã®ãããžã§ã¯ãã®ãã©ã«ããŒã«ãªããŸãã XNUMX ã€äžã®ã¬ãã«ã¯ãçµåãããã³ã³ããŒãã³ãã§ãã
ãã㯠dockerized-app ã®å 容ã®ã¿ã®äŸã§ãã ããã§ã¯ Docker ãã£ã¬ã¯ããªãæã¡åºãããã¹ãŠã®ã³ã³ããŒãã³ãã®å¯Ÿè©±ã«å¿ èŠãªèšå®ãããã«å ¥åããŸãã ãããžã§ã¯ãã®å®è¡æ¹æ³ãç°¡åã«èª¬æãã README.md ããããŸãã
ããã§ã¯ XNUMX ã€ã® docker-compose ãã¡ã€ã«ãé©çšããŸããã ããã¯ã段éçã«å®è¡ã§ããããã«ããããã«è¡ãããŸãã éçºè ãã³ã¢ãæäœããå Žåãããã·ã¥éç¥ã¯å¿ èŠãããŸãããåã« docker-compose ãã¡ã€ã«ãèµ·åããã ãã§ããªãœãŒã¹ãä¿åãããŸãã
ããã·ã¥éç¥ãšçµ±åããå¿ èŠãããå Žåã¯ãdocker-compose.yaml ããã³ docker-compose-push.yaml ãèµ·åãããŸãã
docker-compose.yaml ãš docker-compose-push.yaml ã¯ãã©ã«ããŒå ã«ãããããåäžã®ä»®æ³ãããã¯ãŒã¯ãèªåçã«äœæãããŸãã
ã³ã³ããŒãã³ãã®èª¬æã ããã¯ãã³ã³ããŒãã³ãã®ã³ã¬ã¯ã·ã§ã³ãæ åœãããããé«åºŠãªãã¡ã€ã«ã§ãã ããã§æ³šç®ãã¹ãç¹ã¯äœã§ãã? ããã§ã¯ãã©ã³ãµãŒã³ã³ããŒãã³ãã玹ä»ããŸãã
ããã¯ãnginx ãš Docker ãœã±ããããªãã¹ã³ããã¢ããªã±ãŒã·ã§ã³ãå®è¡ããæ¢è£œã® Docker ã€ã¡ãŒãžã§ãã åçãã³ã³ãããŒããªã³ãŸãã¯ãªãã«ãªããšãnginx æ§æãåçæãããŸãã ã³ã³ããŒãã³ãã®åŠçã第 XNUMX ã¬ãã« ãã¡ã€ã³åããšã«åæ£ããŸãã
éçºç°å¢ã«ã¯ã.dev ãã¡ã€ã³ - api.informer.dev ã䜿çšããŸãã .dev ãã¡ã€ã³ãæã€ã¢ããªã±ãŒã·ã§ã³ã¯ãéçºè ã®ããŒã«ã« ãã·ã³ã§äœ¿çšã§ããŸãã
ããã«ãèšå®ã¯åãããžã§ã¯ãã«è»¢éããããã¹ãŠã®ãããžã§ã¯ããåæã«èµ·åãããŸãã
ã°ã©ãã£ãã¯çã«ã¯ãã¯ã©ã€ã¢ã³ãã¯ãã©ãŠã¶ããŸãã¯ãã©ã³ãµãŒã«ãªã¯ãšã¹ããéä¿¡ããããã®ããŒã«ã§ããããšãããããŸãã
ãã¡ã€ã³åãã©ã³ãµã¯ãã©ã®ã³ã³ããã«æ¥ç¶ãããã決å®ããŸãã
管çè ã« JS ãæäŸãã nginx ã䜿çšããããšãã§ããŸãã ããã¯ãAPI ãæäŸãã nginx ããç»åã¢ããããŒãã®åœ¢åŒã§ nginx ã«æäŸãããéçãã¡ã€ã«ã§ãã
ãã®å³ã¯ãã³ã³ãããŒãä»®æ³ãããã¯ãŒã¯ã«ãã£ãŠæ¥ç¶ããããããã·ã®èåŸã«é ãããŠããããšã瀺ããŠããŸãã
éçºè ã®ãã·ã³ã§ã¯IPãç¥ã£ãŠã³ã³ããã«ã¢ã¯ã»ã¹ã§ããŸãããååãšããŠããã䜿çšããŸããã å®éã«ã¯çŽæ¥ã¢ã¯ã»ã¹ããå¿ èŠã¯ãããŸããã
ã¢ããªã±ãŒã·ã§ã³ã Docker åããã«ã¯ã©ã®äŸãåç §ããã°ããã§ãããã? ç§ã®èãã§ã¯ãè¯ãäŸã¯ MySQL ã®å ¬åŒ Docker ã€ã¡ãŒãžã§ãã
ããã¯ããªãææŠçã§ãã å€ãã®ããŒãžã§ã³ããããŸãã ãã ãããã®æ©èœã«ããããããªãéçºã®éçšã§çºçããå¯èœæ§ã®ããå€ãã®ããŒãºã«å¯Ÿå¿ã§ããŸãã æéããããŠãã¹ãŠãã©ã®ããã«çžäºäœçšããã®ããç解ããã°ãèªå·±å®è£ ã«åé¡ã¯ãªããšæããŸãã
éåžžãHub.docker.com ã«ã¯ github.com ãžã®ãªã³ã¯ãå«ãŸããŠãããããã«ã¯çããŒã¿ãå«ãŸããŠãããããããçŽæ¥ã€ã¡ãŒãžãæ§ç¯ã§ããŸãã
ããã«ããã®ãªããžããªã«ã¯ docker-endpoint.sh ã¹ã¯ãªããããããããã¯åæåæåãšã¢ããªã±ãŒã·ã§ã³èµ·åã®ãã®åŸã®åŠçãæ åœããŸãã
ãã®äŸã§ã¯ãç°å¢å€æ°ã䜿çšããŠæ§æããæ©èœããããŸãã åäžã®ã³ã³ãããŒãå®è¡ãããšãããŸã㯠docker-compose ãéããŠç°å¢å€æ°ãå®çŸ©ããããšã«ãã£ãŠãMySQL ãªã©ã® root ã« docker ã®ç©ºã®ãã¹ã¯ãŒããèšå®ããå¿ èŠããããšèšããŸãã
ã©ã³ãã ãªãã¹ã¯ãŒããäœæãããªãã·ã§ã³ããããŸãã ãŠãŒã¶ãŒãå¿ èŠã§ããŠãŒã¶ãŒã®ãã¹ã¯ãŒããèšå®ããããŒã¿ããŒã¹ãäœæããå¿ èŠããããšèšããŸãã
ç§ãã¡ã®ãããžã§ã¯ãã§ã¯ãåæåãæ åœãã Dockerfile ããããã«çµ±åããŸããã ããã§ãã¢ããªã±ãŒã·ã§ã³ã䜿çšãããŠãŒã¶ãŒæš©éã®åãªãæ¡åŒµãšãªãããã«ãããŒãºã«åãããŠä¿®æ£ããŸããã ããã«ãããåŸã§ã¢ããªã±ãŒã·ã§ã³ ã³ã³ãœãŒã«ããããŒã¿ããŒã¹ãç°¡åã«äœæã§ããããã«ãªããŸããã Ruby ã¢ããªã±ãŒã·ã§ã³ã«ã¯ãããŒã¿ããŒã¹ãäœæãå€æŽãåé€ããããã®ã³ãã³ãããããŸãã
ããã¯ãgithub.com ã§ã® MySQL ã®ç¹å®ã®ããŒãžã§ã³ãã©ã®ããã«èŠãããã瀺ãäŸã§ãã Dockerfile ãéããŠãããã§ã€ã³ã¹ããŒã«ãã©ã®ããã«è¡ãããŠãããã確èªã§ããŸãã
docker-endpoint.sh ã¯ããšã³ã㪠ãã€ã³ããæ åœããã¹ã¯ãªããã§ãã æåã®åæåäžã«ã¯ãããã€ãã®æºåæé ãå¿ èŠã§ããããããã®ã¢ã¯ã·ã§ã³ã¯ãã¹ãŠåæåã¹ã¯ãªããå ã§å®è¡ãããŸãã
ã§ã¯ã第 XNUMX éšã«é²ã¿ãŸãããã
ãœãŒã¹ã³ãŒããä¿åããããã«ãgitlab ã«åãæ¿ããŸããã ããã¯ãèŠèŠçãªã€ã³ã¿ãŒãã§ã€ã¹ãåããéåžžã«åŒ·åãªã·ã¹ãã ã§ãã
Gitlab ã®ã³ã³ããŒãã³ãã® XNUMX ã€ã¯ Gitlab CI ã§ãã ããã«ãããåŸã§ã³ãŒãé ä¿¡ã·ã¹ãã ãç·šæããããèªåãã¹ããå®è¡ãããããããã«äœ¿çšãããäžé£ã®ã³ãã³ããèšè¿°ããããšãã§ããŸãã
Gitlab CI 2 ã®ããŒã¯
次ã«ãGitlab CI ãã¢ã¯ãã£ãåããããã«å¿ èŠãªãã®ãèŠãŠãããŸãã Gitlab CI ãéå§ããã«ã¯ã.gitlab-ci.yml ãã¡ã€ã«ããããžã§ã¯ãã®ã«ãŒãã«é 眮ããã ãã§ãã
ããã§ã¯ããã¹ãããããã€ãªã©ã®äžé£ã®ç¶æ ãå®è¡ãããããšã説æããŸãã
docker-compose ãçŽæ¥åŒã³åºãã¹ã¯ãªãããå®è¡ããŠã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããŸãã ããã¯åãªãããã¯ãšã³ãã®äŸã§ãã
次ã«ãããŒã¿ããŒã¹ãå€æŽããŠãã¹ããå®è¡ããããã«ç§»è¡ãå®è¡ããå¿ èŠããããšããŸãã
ã¹ã¯ãªãããæ£ããå®è¡ããããšã©ãŒ ã³ãŒããè¿ãããªãå Žåãã·ã¹ãã ã¯å±éã®ç¬¬ XNUMX 段éã«é²ã¿ãŸãã
çŸåšãå±éã¹ããŒãžã¯ã¹ããŒãžã³ã°çšã«å®è£ ãããŠããŸãã ç§ãã¡ã¯ããŠã³ã¿ã€ã ãŒãã®åèµ·åãèšç»ããŸããã§ããã
å šãŠã®å®¹åšã匷å¶çã«æ¶ç«ããè©Šéšã®ç¬¬äžæ®µéã§ååããå šãŠã®å®¹åšãå床åŒãäžããŸãã
çŸåšã®ç°å¢å€æ°ã«å¯ŸããŠãéçºè ã«ãã£ãŠäœæãããããŒã¿ããŒã¹ç§»è¡ãå®è¡ããŠããŸãã
ãã㯠master ãã©ã³ãã«ã®ã¿é©çšããããšãã泚æäºé ããããŸãã
å€æŽæã¯ä»ã®åå²ã¯å®è¡ãããŸããã
ããŒã«ã¢ãŠãããã©ã³ãããšã«æŽçããããšãã§ããŸãã
ãããããã«æŽçããã«ã¯ãGitlab Runner ãã€ã³ã¹ããŒã«ããå¿ èŠããããŸãã
ãã®ãŠãŒãã£ãªãã£ã¯ Golang ã§æžãããŠããŸãã Golang ã®äžçã§ã¯äžè¬çã§ããããã«ãããã¯åäžã®ãã¡ã€ã«ã§ãããäŸåé¢ä¿ãå¿ èŠãšããŸããã
èµ·åæã«ãGitlab Runner ãç»é²ããŸãã
Gitlab Web ã€ã³ã¿ãŒãã§ã€ã¹ã§ããŒãååŸããŸãã
次ã«ãã³ãã³ã ã©ã€ã³ã§åæåã³ãã³ããåŒã³åºããŸãã
Gitlab Runner ã察話çã«ã»ããã¢ãããã (ã·ã§ã«ãDockerãVirtualBoxãSSH)
Gitlab Runner ã®ã³ãŒãã¯ã.gitlab-ci.yml èšå®ã«å¿ããŠãã³ãããããšã«å®è¡ãããŸãã
Web ã€ã³ã¿ãŒãã§ã€ã¹ã® Gitlab ã§èŠèŠçã«ã©ã®ããã«èŠãããã GItlab CI ã«æ¥ç¶ãããšãçŸæç¹ã§ã®ãã«ãã®ç¶æ ã瀺ããã©ã°ã衚瀺ãããŸãã
ã³ãããã 4 ååã«è¡ããããã¹ãŠã®ãã¹ãã«åæ Œããåé¡ãçºçããªãã£ãããšãããããŸãã
ãã«ãã詳ããèŠãŠã¿ãŸãããã ããã§ã¯ãXNUMX ã€ã®å·ããã§ã«ééããŠããããšãããããŸãã ã¹ããŒãžã³ã°äžã®ãã¹ã ã¹ããŒã¿ã¹ãšãããã€ã¡ã³ã ã¹ããŒã¿ã¹ã
ç¹å®ã®ãã«ããã¯ãªãã¯ãããšã.gitlab-ci.yml ã«åŸã£ãŠããã»ã¹ã§å®è¡ãããã³ãã³ãã®ã³ã³ãœãŒã«åºåã衚瀺ãããŸãã
åŒç€Ÿã®è£œåã®æŽå²ã¯ãããªæãã§ãã è©Šã¿ãæåããããšãããããŸãã ãã¹ããéä¿¡ãããŠãââã次ã®ã¹ãããã«ã¯é²ãŸããã¹ããŒãžã³ã° ã³ãŒãã¯æŽæ°ãããŸããã
Docker ãå®è£ ãããšãã«ã¹ããŒãžã³ã°ã§ã©ã®ãããªã¿ã¹ã¯ã解決ããŸããã? ç§ãã¡ã®ã·ã¹ãã ã¯ã³ã³ããŒãã³ãã§æ§æãããŠãããã·ã¹ãã å šäœã§ã¯ãªãããªããžããªå ã§æŽæ°ãããã³ã³ããŒãã³ãã®äžéšã®ã¿ãåèµ·åããå¿ èŠããããŸããã
ãããè¡ãã«ã¯ããã¹ãŠãå¥ã ã®ãã©ã«ããŒã«åå²ããå¿ èŠããããŸããã
ãããå®è¡ããåŸãDocker-compose ãããããšã«ç¬èªã®ãããã¯ãŒã¯ ã¹ããŒã¹ãäœæããè¿é£ã®ã³ã³ããŒãã³ãã衚瀺ãããªããšããåé¡ãçºçããŸããã
ãããåé¿ããããã«ãDocker ã§ãããã¯ãŒã¯ãæåã§äœæããŸããã ãã®ãããžã§ã¯ãã§ã¯ãã®ãããªãããã¯ãŒã¯ã䜿çšããããšã Docker-compose ã§æžãããŠããŸãã
ãããã£ãŠããã®ã¡ãã·ã¥ã§å§ãŸããã¹ãŠã®ã³ã³ããŒãã³ãã¯ãã·ã¹ãã ã®ä»ã®éšåã®ã³ã³ããŒãã³ããåç §ããŸãã
次ã®åé¡ã¯ãã¹ããŒãžã³ã°ãè€æ°ã®ãããžã§ã¯ãã«åå²ããããšã§ãã
ããããã¹ãŠãçŸãããæ¬çªç°å¢ã«ã§ããã ãè¿ã¥ããããã«ã¯ãWeb ã®ããããå Žæã§äœ¿çšãããŠããããŒã 80 ãŸã㯠443 ã䜿çšããã®ãè¯ãã§ãããã
ã©ããã£ãŠè§£æ±ºããã®ã§ããããïŒ ãã¹ãŠã®äž»èŠãããžã§ã¯ãã« XNUMX 人㮠Gitlab Runner ãå²ãåœãŠãŸããã
Gitlab ã§ã¯ãè€æ°ã®åæ£ Gitlab Runner ãå®è¡ã§ããŸããããã«ããããã¹ãŠã®ã¿ã¹ã¯ãç¡ç§©åºã«é çªã«å®è¡ãããŸãã
家ãæããªãããã«ããããžã§ã¯ãã®ã°ã«ãŒãã XNUMX ã€ã® Gitlab Runner ã«éå®ããŸãããGitlab Runner ã¯ããªã¥ãŒã ã«åé¡ãªã察å¿ã§ããŸãã
nginx-proxy ãå¥ã®èµ·åã¹ã¯ãªããã«ç§»åãããã®ã¹ã¯ãªããã«ãã¹ãŠã®ãããžã§ã¯ãã®ã°ãªãããè¿œå ããŸããã
ç§ãã¡ã®ãããžã§ã¯ãã«ã¯ XNUMX ã€ã®ã°ãªãããããããã©ã³ãµãŒã«ã¯ãããžã§ã¯ãåããšã«è€æ°ã®ã°ãªããããããŸãã ããã«ãã¡ã€ã³åã«ãã£ãŠãããã·ããããšãã§ããŸãã
ãªã¯ãšã¹ãã¯ããŒã 80 ã®ãã¡ã€ã³ãä»ããŠåä¿¡ããããã®ãã¡ã€ã³ã«ãµãŒãã¹ãæäŸããã³ã³ãã㌠ã°ã«ãŒãã«è§£æ±ºãããŸãã
ä»ã«ã©ã®ãããªåé¡ããããŸããã? ããã¯ããã¹ãŠã®ã³ã³ãããããã©ã«ã㧠root ãšããŠå®è¡ããããã®ã§ãã ããã¯ãã·ã¹ãã ã®ã«ãŒã ãã¹ããšã¯ç°ãªãã«ãŒãã§ãã
ãã ããã³ã³ããã«å ¥ããšã«ãŒãã«ãªãããã®ã³ã³ããå ã«äœæãããã¡ã€ã«ã¯ã«ãŒãæš©éãååŸããŸãã
éçºè ãã³ã³ããã«å ¥ããããã§ãã¡ã€ã«ãçæããããã€ãã®ã³ãã³ããå®è¡ããŠããã³ã³ãããé¢ããå Žåãéçºè ã®äœæ¥ãã£ã¬ã¯ããªã«ã¯ã¢ã¯ã»ã¹æš©ã®ãªããã¡ã€ã«ãååšããŸãã
ã©ãããã°è§£æ±ºã§ããŸãã? ã³ã³ããå ã«ååšãããŠãŒã¶ãŒãè¿œå ã§ããŸãã
ãŠãŒã¶ãŒãè¿œå ãããšãã«ã©ã®ãããªåé¡ãçºçããŸããã?
ãŠãŒã¶ãŒãäœæãããšããåãã°ã«ãŒã ID (UID) ãšãŠãŒã¶ãŒ ID (GID) ããªãããšããããããŸãã
ã³ã³ãããŒå ã§ãã®åé¡ã解決ããã«ã¯ãID 1000 ã®ãŠãŒã¶ãŒã䜿çšããŸãã
ç§ãã¡ã®å Žåãããã¯ã»ãŒãã¹ãŠã®éçºè ã Ubuntu OS ã䜿çšããŠãããšããäºå®ãšäžèŽããŸããã Ubuntu ã§ã¯ãæåã®ãŠãŒã¶ãŒã® ID 㯠1000 ã§ãã
èšç»ã¯ãããŸãã?
Docker ã®ããã¥ã¡ã³ããèªãã§ãã ããã ãããžã§ã¯ãã¯æŽ»çºã«éçºãããŠãããããã¥ã¡ã³ãã¯å€æŽãããŠããŸãã XNUMX ïœ XNUMX ãæåã«åãåã£ãããŒã¿ã¯ããã§ã«åŸã ã«å€ããªãã€ã€ãããŸãã
ç§ãã¡ã解決ããåé¡ã®äžéšã¯ãæšæºçãªæ段ã§ãã§ã«è§£æ±ºãããŠããå¯èœæ§ããããŸãã
ãããã£ãŠãç§ã¯ããã«é²ãã§ããªãŒã±ã¹ãã¬ãŒã·ã§ã³ã«çŽæ¥é²ã¿ãããšèããŠããŸãã
äžäŸãšããŠãããã«äœ¿ãã Docker Swarm ãšåŒã°ãã Docker ã®çµã¿èŸŒã¿ã¡ã«ããºã ããããŸãã Docker Swarm ãã¯ãããžãŒã«åºã¥ããŠå®çšŒåç°å¢ã§äœããå®è¡ããããšèããŠããŸãã
ã³ã³ãããŒãçæãããšããã°ã®æäœãäžäŸ¿ã«ãªããŸãã ããã§ãã°ãåé¢ãããŸããã ãããã¯ã³ã³ããå šäœã«æ£ãã°ã£ãŠããŸãã ã¿ã¹ã¯ã® XNUMX ã€ã¯ãWeb ã€ã³ã¿ãŒãã§ã€ã¹ãéããŠãã°ã«ç°¡åã«ã¢ã¯ã»ã¹ã§ããããã«ããããšã§ãã
åºæïŒ habr.com