[{"data":1,"prerenderedAt":996},["ShallowReactive",2],{"/ja-jp/blog/categories/engineering/":3,"navigation-ja-jp":22,"banner-ja-jp":439,"footer-ja-jp":452,"engineering-category-page-ja-jp":663},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":11,"config":12,"_id":15,"_type":16,"title":17,"_source":18,"_file":19,"_stem":20,"_extension":21},"/ja-jp/blog/categories/engineering","categories",false,"",{"title":9,"description":10},"エンジニアリング","Browse articles related to エンジニアリング on the GitLab Blog",{"name":9},{"template":13,"slug":14,"hide":6},"BlogCategory","engineering","content:ja-jp:blog:categories:engineering.yml","yaml","Engineering","content","ja-jp/blog/categories/engineering.yml","ja-jp/blog/categories/engineering","yml",{"_path":23,"_dir":24,"_draft":6,"_partial":6,"_locale":7,"data":25,"_id":435,"_type":16,"title":436,"_source":18,"_file":437,"_stem":438,"_extension":21},"/shared/ja-jp/main-navigation","ja-jp",{"logo":26,"freeTrial":31,"sales":36,"login":41,"items":46,"search":379,"minimal":413,"duo":426},{"config":27},{"href":28,"dataGaName":29,"dataGaLocation":30},"/ja-jp/","gitlab logo","header",{"text":32,"config":33},"無料トライアルを開始",{"href":34,"dataGaName":35,"dataGaLocation":30},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":37,"config":38},"お問い合わせ",{"href":39,"dataGaName":40,"dataGaLocation":30},"/ja-jp/sales/","sales",{"text":42,"config":43},"サインイン",{"href":44,"dataGaName":45,"dataGaLocation":30},"https://gitlab.com/users/sign_in/","sign in",[47,91,190,195,301,361],{"text":48,"config":49,"cards":51,"footer":74},"プラットフォーム",{"dataNavLevelOne":50},"platform",[52,58,66],{"title":48,"description":53,"link":54},"最も包括的かつAIで強化されたDevSecOpsプラットフォーム",{"text":55,"config":56},"プラットフォームを詳しく見る",{"href":57,"dataGaName":50,"dataGaLocation":30},"/ja-jp/platform/",{"title":59,"description":60,"link":61},"GitLab Duo（AI）","開発のすべてのステージでAIを活用し、ソフトウェアをより迅速にビルド",{"text":62,"config":63},"GitLab Duoのご紹介",{"href":64,"dataGaName":65,"dataGaLocation":30},"/ja-jp/gitlab-duo/","gitlab duo ai",{"title":67,"description":68,"link":69},"GitLabが選ばれる理由","GitLabが大企業に選ばれる理由10選",{"text":70,"config":71},"詳細はこちら",{"href":72,"dataGaName":73,"dataGaLocation":30},"/ja-jp/why-gitlab/","why gitlab",{"title":75,"items":76},"利用を開始：",[77,82,87],{"text":78,"config":79},"プラットフォームエンジニアリング",{"href":80,"dataGaName":81,"dataGaLocation":30},"/ja-jp/solutions/platform-engineering/","platform engineering",{"text":83,"config":84},"開発者の経験",{"href":85,"dataGaName":86,"dataGaLocation":30},"/ja-jp/developer-experience/","Developer experience",{"text":88,"config":89},"MLOps",{"href":90,"dataGaName":88,"dataGaLocation":30},"/ja-jp/topics/devops/the-role-of-ai-in-devops/",{"text":92,"left":93,"config":94,"link":96,"lists":100,"footer":172},"製品",true,{"dataNavLevelOne":95},"solutions",{"text":97,"config":98},"すべてのソリューションを表示",{"href":99,"dataGaName":95,"dataGaLocation":30},"/ja-jp/solutions/",[101,127,150],{"title":102,"description":103,"link":104,"items":109},"自動化","CI/CDと自動化でデプロイを加速",{"config":105},{"icon":106,"href":107,"dataGaName":108,"dataGaLocation":30},"AutomatedCodeAlt","/ja-jp/solutions/delivery-automation/","automated software delivery",[110,114,118,123],{"text":111,"config":112},"CI/CD",{"href":113,"dataGaLocation":30,"dataGaName":111},"/ja-jp/solutions/continuous-integration/",{"text":115,"config":116},"AIアシストによる開発",{"href":64,"dataGaLocation":30,"dataGaName":117},"AI assisted development",{"text":119,"config":120},"ソースコード管理",{"href":121,"dataGaLocation":30,"dataGaName":122},"/ja-jp/solutions/source-code-management/","Source Code Management",{"text":124,"config":125},"自動化されたソフトウェアデリバリー",{"href":107,"dataGaLocation":30,"dataGaName":126},"Automated software delivery",{"title":128,"description":129,"link":130,"items":135},"セキュリティ","セキュリティを損なうことなくコードをより迅速に完成",{"config":131},{"href":132,"dataGaName":133,"dataGaLocation":30,"icon":134},"/ja-jp/solutions/security-compliance/","security and compliance","ShieldCheckLight",[136,140,145],{"text":137,"config":138},"セキュリティとコンプライアンス",{"href":132,"dataGaLocation":30,"dataGaName":139},"Security & Compliance",{"text":141,"config":142},"ソフトウェアサプライチェーンの安全性",{"href":143,"dataGaLocation":30,"dataGaName":144},"/ja-jp/solutions/supply-chain/","Software supply chain security",{"text":146,"config":147},"コンプライアンスとガバナンス",{"href":148,"dataGaLocation":30,"dataGaName":149},"/ja-jp/solutions/continuous-software-compliance/","Compliance and governance",{"title":151,"link":152,"items":157},"測定",{"config":153},{"icon":154,"href":155,"dataGaName":156,"dataGaLocation":30},"DigitalTransformation","/ja-jp/solutions/visibility-measurement/","visibility and measurement",[158,162,167],{"text":159,"config":160},"可視性と測定",{"href":155,"dataGaLocation":30,"dataGaName":161},"Visibility and Measurement",{"text":163,"config":164},"バリューストリーム管理",{"href":165,"dataGaLocation":30,"dataGaName":166},"/ja-jp/solutions/value-stream-management/","Value Stream Management",{"text":168,"config":169},"分析とインサイト",{"href":170,"dataGaLocation":30,"dataGaName":171},"/ja-jp/solutions/analytics-and-insights/","Analytics and insights",{"title":173,"items":174},"GitLabが活躍する場所",[175,180,185],{"text":176,"config":177},"Enterprise",{"href":178,"dataGaLocation":30,"dataGaName":179},"/ja-jp/enterprise/","enterprise",{"text":181,"config":182},"スモールビジネス",{"href":183,"dataGaLocation":30,"dataGaName":184},"/ja-jp/small-business/","small business",{"text":186,"config":187},"公共機関",{"href":188,"dataGaLocation":30,"dataGaName":189},"/ja-jp/solutions/public-sector/","public sector",{"text":191,"config":192},"価格",{"href":193,"dataGaName":194,"dataGaLocation":30,"dataNavLevelOne":194},"/ja-jp/pricing/","pricing",{"text":196,"config":197,"link":199,"lists":203,"feature":288},"関連リソース",{"dataNavLevelOne":198},"resources",{"text":200,"config":201},"すべてのリソースを表示",{"href":202,"dataGaName":198,"dataGaLocation":30},"/ja-jp/resources/",[204,237,260],{"title":205,"items":206},"はじめに",[207,212,217,222,227,232],{"text":208,"config":209},"インストール",{"href":210,"dataGaName":211,"dataGaLocation":30},"/ja-jp/install/","install",{"text":213,"config":214},"クイックスタートガイド",{"href":215,"dataGaName":216,"dataGaLocation":30},"/ja-jp/get-started/","quick setup checklists",{"text":218,"config":219},"学ぶ",{"href":220,"dataGaLocation":30,"dataGaName":221},"https://university.gitlab.com/","learn",{"text":223,"config":224},"製品ドキュメント",{"href":225,"dataGaName":226,"dataGaLocation":30},"https://docs.gitlab.com/","product documentation",{"text":228,"config":229},"ベストプラクティスビデオ",{"href":230,"dataGaName":231,"dataGaLocation":30},"/ja-jp/getting-started-videos/","best practice videos",{"text":233,"config":234},"インテグレーション",{"href":235,"dataGaName":236,"dataGaLocation":30},"/ja-jp/integrations/","integrations",{"title":238,"items":239},"検索する",[240,245,250,255],{"text":241,"config":242},"お客様成功事例",{"href":243,"dataGaName":244,"dataGaLocation":30},"/customers/","customer success stories",{"text":246,"config":247},"ブログ",{"href":248,"dataGaName":249,"dataGaLocation":30},"/ja-jp/blog/","blog",{"text":251,"config":252},"リモート",{"href":253,"dataGaName":254,"dataGaLocation":30},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":256,"config":257},"TeamOps",{"href":258,"dataGaName":259,"dataGaLocation":30},"/ja-jp/teamops/","teamops",{"title":261,"items":262},"つなげる",[263,268,273,278,283],{"text":264,"config":265},"GitLabサービス",{"href":266,"dataGaName":267,"dataGaLocation":30},"/ja-jp/services/","services",{"text":269,"config":270},"コミュニティ",{"href":271,"dataGaName":272,"dataGaLocation":30},"/community/","community",{"text":274,"config":275},"フォーラム",{"href":276,"dataGaName":277,"dataGaLocation":30},"https://forum.gitlab.com/","forum",{"text":279,"config":280},"イベント",{"href":281,"dataGaName":282,"dataGaLocation":30},"/events/","events",{"text":284,"config":285},"パートナー",{"href":286,"dataGaName":287,"dataGaLocation":30},"/ja-jp/partners/","partners",{"backgroundColor":289,"textColor":290,"text":291,"image":292,"link":296},"#2f2a6b","#fff","ソフトウェア開発の未来への洞察",{"altText":293,"config":294},"ソースプロモカード",{"src":295},"/images/navigation/the-source-promo-card.svg",{"text":297,"config":298},"最新情報を読む",{"href":299,"dataGaName":300,"dataGaLocation":30},"/ja-jp/the-source/","the source",{"text":302,"config":303,"lists":305},"Company",{"dataNavLevelOne":304},"company",[306],{"items":307},[308,313,319,321,326,331,336,341,346,351,356],{"text":309,"config":310},"GitLabについて",{"href":311,"dataGaName":312,"dataGaLocation":30},"/ja-jp/company/","about",{"text":314,"config":315,"footerGa":318},"採用情報",{"href":316,"dataGaName":317,"dataGaLocation":30},"/jobs/","jobs",{"dataGaName":317},{"text":279,"config":320},{"href":281,"dataGaName":282,"dataGaLocation":30},{"text":322,"config":323},"経営陣",{"href":324,"dataGaName":325,"dataGaLocation":30},"/company/team/e-group/","leadership",{"text":327,"config":328},"チーム",{"href":329,"dataGaName":330,"dataGaLocation":30},"/company/team/","team",{"text":332,"config":333},"ハンドブック",{"href":334,"dataGaName":335,"dataGaLocation":30},"https://handbook.gitlab.com/","handbook",{"text":337,"config":338},"投資家向け情報",{"href":339,"dataGaName":340,"dataGaLocation":30},"https://ir.gitlab.com/","investor relations",{"text":342,"config":343},"トラストセンター",{"href":344,"dataGaName":345,"dataGaLocation":30},"/ja-jp/security/","trust center",{"text":347,"config":348},"AI Transparency Center",{"href":349,"dataGaName":350,"dataGaLocation":30},"/ja-jp/ai-transparency-center/","ai transparency center",{"text":352,"config":353},"ニュースレター",{"href":354,"dataGaName":355,"dataGaLocation":30},"/company/contact/","newsletter",{"text":357,"config":358},"プレス",{"href":359,"dataGaName":360,"dataGaLocation":30},"/press/","press",{"text":37,"config":362,"lists":363},{"dataNavLevelOne":304},[364],{"items":365},[366,369,374],{"text":37,"config":367},{"href":39,"dataGaName":368,"dataGaLocation":30},"talk to sales",{"text":370,"config":371},"サポートを受ける",{"href":372,"dataGaName":373,"dataGaLocation":30},"/support/","get help",{"text":375,"config":376},"カスタマーポータル",{"href":377,"dataGaName":378,"dataGaLocation":30},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":380,"login":381,"suggestions":388},"閉じる",{"text":382,"link":383},"リポジトリとプロジェクトを検索するには、次にログインします",{"text":384,"config":385},"GitLab.com",{"href":44,"dataGaName":386,"dataGaLocation":387},"search login","search",{"text":389,"default":390},"提案",[391,394,399,401,405,409],{"text":59,"config":392},{"href":64,"dataGaName":393,"dataGaLocation":387},"GitLab Duo (AI)",{"text":395,"config":396},"コード提案（AI）",{"href":397,"dataGaName":398,"dataGaLocation":387},"/ja-jp/solutions/code-suggestions/","Code Suggestions (AI)",{"text":111,"config":400},{"href":113,"dataGaName":111,"dataGaLocation":387},{"text":402,"config":403},"GitLab on AWS",{"href":404,"dataGaName":402,"dataGaLocation":387},"/ja-jp/partners/technology-partners/aws/",{"text":406,"config":407},"GitLab on Google Cloud",{"href":408,"dataGaName":406,"dataGaLocation":387},"/ja-jp/partners/technology-partners/google-cloud-platform/",{"text":410,"config":411},"GitLabを選ぶ理由",{"href":72,"dataGaName":412,"dataGaLocation":387},"Why GitLab?",{"freeTrial":414,"mobileIcon":418,"desktopIcon":423},{"text":32,"config":415},{"href":416,"dataGaName":35,"dataGaLocation":417},"https://gitlab.com/-/trials/new/","nav",{"altText":419,"config":420},"GitLabアイコン",{"src":421,"dataGaName":422,"dataGaLocation":417},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":419,"config":424},{"src":425,"dataGaName":422,"dataGaLocation":417},"/images/brand/gitlab-logo-type.svg",{"freeTrial":427,"mobileIcon":431,"desktopIcon":433},{"text":428,"config":429},"GitLab Duoの詳細について",{"href":64,"dataGaName":430,"dataGaLocation":417},"gitlab duo",{"altText":419,"config":432},{"src":421,"dataGaName":422,"dataGaLocation":417},{"altText":419,"config":434},{"src":425,"dataGaName":422,"dataGaLocation":417},"content:shared:ja-jp:main-navigation.yml","Main Navigation","shared/ja-jp/main-navigation.yml","shared/ja-jp/main-navigation",{"_path":440,"_dir":24,"_draft":6,"_partial":6,"_locale":7,"title":441,"titleMobile":441,"button":442,"config":447,"_id":449,"_type":16,"_source":18,"_file":450,"_stem":451,"_extension":21},"/shared/ja-jp/banner","GitLab 18と知的進化する次世代のDevSecOps。6月24日のオンラインイベントにご参加ください。",{"text":443,"config":444},"今すぐ申し込む",{"href":445,"dataGaName":446,"dataGaLocation":30},"/ja-jp/eighteen/","gitlab 18 banner",{"layout":448},"release","content:shared:ja-jp:banner.yml","shared/ja-jp/banner.yml","shared/ja-jp/banner",{"_path":453,"_dir":24,"_draft":6,"_partial":6,"_locale":7,"data":454,"_id":659,"_type":16,"title":660,"_source":18,"_file":661,"_stem":662,"_extension":21},"/shared/ja-jp/main-footer",{"text":455,"source":456,"edit":462,"contribute":467,"config":472,"items":477,"minimal":651},"GitはSoftware Freedom Conservancyの商標です。当社は「GitLab」をライセンスに基づいて使用しています",{"text":457,"config":458},"ページのソースを表示",{"href":459,"dataGaName":460,"dataGaLocation":461},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":463,"config":464},"このページを編集",{"href":465,"dataGaName":466,"dataGaLocation":461},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":468,"config":469},"ご協力をお願いします",{"href":470,"dataGaName":471,"dataGaLocation":461},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":473,"facebook":474,"youtube":475,"linkedin":476},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[478,501,555,588,623],{"title":48,"links":479,"subMenu":484},[480],{"text":481,"config":482},"DevSecOpsプラットフォーム",{"href":57,"dataGaName":483,"dataGaLocation":461},"devsecops platform",[485],{"title":191,"links":486},[487,491,496],{"text":488,"config":489},"プランの表示",{"href":193,"dataGaName":490,"dataGaLocation":461},"view plans",{"text":492,"config":493},"Premiumを選ぶ理由",{"href":494,"dataGaName":495,"dataGaLocation":461},"/ja-jp/pricing/premium/","why premium",{"text":497,"config":498},"Ultimateを選ぶ理由",{"href":499,"dataGaName":500,"dataGaLocation":461},"/ja-jp/pricing/ultimate/","why ultimate",{"title":502,"links":503},"ソリューション",[504,509,512,514,519,524,528,531,534,539,541,543,545,550],{"text":505,"config":506},"デジタルトランスフォーメーション",{"href":507,"dataGaName":508,"dataGaLocation":461},"/solutions/digital-transformation/","digital transformation",{"text":137,"config":510},{"href":132,"dataGaName":511,"dataGaLocation":461},"security & compliance",{"text":124,"config":513},{"href":107,"dataGaName":108,"dataGaLocation":461},{"text":515,"config":516},"アジャイル開発",{"href":517,"dataGaName":518,"dataGaLocation":461},"/ja-jp/solutions/agile-delivery/","agile delivery",{"text":520,"config":521},"クラウドトランスフォーメーション",{"href":522,"dataGaName":523,"dataGaLocation":461},"/ja-jp/solutions/cloud-native/","cloud transformation",{"text":525,"config":526},"SCM",{"href":121,"dataGaName":527,"dataGaLocation":461},"source code management",{"text":111,"config":529},{"href":113,"dataGaName":530,"dataGaLocation":461},"continuous integration & delivery",{"text":163,"config":532},{"href":165,"dataGaName":533,"dataGaLocation":461},"value stream management",{"text":535,"config":536},"GitOps",{"href":537,"dataGaName":538,"dataGaLocation":461},"/ja-jp/solutions/gitops/","gitops",{"text":176,"config":540},{"href":178,"dataGaName":179,"dataGaLocation":461},{"text":181,"config":542},{"href":183,"dataGaName":184,"dataGaLocation":461},{"text":186,"config":544},{"href":188,"dataGaName":189,"dataGaLocation":461},{"text":546,"config":547},"教育",{"href":548,"dataGaName":549,"dataGaLocation":461},"/ja-jp/solutions/education/","education",{"text":551,"config":552},"金融サービス",{"href":553,"dataGaName":554,"dataGaLocation":461},"/ja-jp/solutions/finance/","financial services",{"title":196,"links":556},[557,559,561,563,566,568,571,573,575,578,580,582,584,586],{"text":208,"config":558},{"href":210,"dataGaName":211,"dataGaLocation":461},{"text":213,"config":560},{"href":215,"dataGaName":216,"dataGaLocation":461},{"text":218,"config":562},{"href":220,"dataGaName":221,"dataGaLocation":461},{"text":223,"config":564},{"href":225,"dataGaName":565,"dataGaLocation":461},"docs",{"text":246,"config":567},{"href":248,"dataGaName":249},{"text":569,"config":570},"お客様の成功事例",{"href":243,"dataGaLocation":461},{"text":241,"config":572},{"href":243,"dataGaName":244,"dataGaLocation":461},{"text":251,"config":574},{"href":253,"dataGaName":254,"dataGaLocation":461},{"text":264,"config":576},{"href":577,"dataGaName":267,"dataGaLocation":461},"/services/",{"text":256,"config":579},{"href":258,"dataGaName":259,"dataGaLocation":461},{"text":269,"config":581},{"href":271,"dataGaName":272,"dataGaLocation":461},{"text":274,"config":583},{"href":276,"dataGaName":277,"dataGaLocation":461},{"text":279,"config":585},{"href":281,"dataGaName":282,"dataGaLocation":461},{"text":284,"config":587},{"href":286,"dataGaName":287,"dataGaLocation":461},{"title":302,"links":589},[590,592,594,596,598,600,602,607,612,614,616,618],{"text":309,"config":591},{"href":311,"dataGaName":304,"dataGaLocation":461},{"text":314,"config":593},{"href":316,"dataGaName":317,"dataGaLocation":461},{"text":322,"config":595},{"href":324,"dataGaName":325,"dataGaLocation":461},{"text":327,"config":597},{"href":329,"dataGaName":330,"dataGaLocation":461},{"text":332,"config":599},{"href":334,"dataGaName":335,"dataGaLocation":461},{"text":337,"config":601},{"href":339,"dataGaName":340,"dataGaLocation":461},{"text":603,"config":604},"環境、社会、ガバナンス（ESG）",{"href":605,"dataGaName":606,"dataGaLocation":461},"/ja-jp/environmental-social-governance/","environmental, social and governance",{"text":608,"config":609},"ダイバーシティ、インクルージョン、ビロンギング（DIB）",{"href":610,"dataGaName":611,"dataGaLocation":461},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":342,"config":613},{"href":344,"dataGaName":345,"dataGaLocation":461},{"text":352,"config":615},{"href":354,"dataGaName":355,"dataGaLocation":461},{"text":357,"config":617},{"href":359,"dataGaName":360,"dataGaLocation":461},{"text":619,"config":620},"現代奴隷制の透明性に関する声明",{"href":621,"dataGaName":622,"dataGaLocation":461},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":37,"links":624},[625,627,629,631,636,641,646],{"text":37,"config":626},{"href":39,"dataGaName":40,"dataGaLocation":461},{"text":370,"config":628},{"href":372,"dataGaName":373,"dataGaLocation":461},{"text":375,"config":630},{"href":377,"dataGaName":378,"dataGaLocation":461},{"text":632,"config":633},"ステータス",{"href":634,"dataGaName":635,"dataGaLocation":461},"https://status.gitlab.com/","status",{"text":637,"config":638},"利用規約",{"href":639,"dataGaName":640,"dataGaLocation":461},"/terms/","terms of use",{"text":642,"config":643},"プライバシーに関する声明",{"href":644,"dataGaLocation":461,"dataGaName":645},"/privacy/","privacy statement",{"text":647,"config":648},"Cookieの設定",{"dataGaName":649,"dataGaLocation":461,"id":650,"isOneTrustButton":93},"cookie preferences","ot-sdk-btn",{"items":652},[653,655,657],{"text":637,"config":654},{"href":639,"dataGaName":640,"dataGaLocation":461},{"text":642,"config":656},{"href":644,"dataGaName":645,"dataGaLocation":461},{"text":647,"config":658},{"dataGaName":649,"dataGaLocation":461,"id":650,"isOneTrustButton":93},"content:shared:ja-jp:main-footer.yml","Main Footer","shared/ja-jp/main-footer.yml","shared/ja-jp/main-footer",{"featuredPost":664,"allPosts":692,"totalPages":994,"initialPosts":995},{"_path":665,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":666,"content":669,"config":685,"_id":688,"_type":16,"title":689,"_source":18,"_file":690,"_stem":691,"_extension":21},"/ja-jp/blog/what-is-docker",{"noIndex":6,"description":667,"title":668},"Dockerのコンテナ技術は広く普及しつつあります。Dockerとは何なのか。Dockerの使い方は？Dockerプラットフォームとその技術の基礎を学びましょう。","Dockerとは：GitLabとの統合とコンテナについての入門編 | GitLab",{"title":670,"description":671,"authors":672,"date":674,"body":675,"category":14,"heroImage":676,"tags":677},"Dockerとは：超入門編","Dockerのコンテナ技術は広く普及しつつあります。Dockerとは何なのか。Dockerの使い方は？Dockerプラットフォームとその技術の基礎を学びましょう。\n",[673],"GitLab Team","2025-06-18","Dockerコンテナ技術は、2013年にオープンソースの「Dockerエンジン」として公開され、翌年2014年には本番環境向けの商用版が発表されました。その後約10年の間に、Dockerは使いやすさと高い利便性から、IT業界で瞬く間に広く普及してきました。これからもその人気は高まっていくでしょう。\n\nしかしその一方で、いまだに「Dockerとは何ですか」という声もよく耳にします。この記事では、Docker環境の導入を検討中で、Dockerにまだ不慣れなデベロッパーやプログラマーの皆様を対象に、Dockerの基本を解説します。Dockerに触れたことのない初心者向けの「Docker超入門編」です。\n\n## 目次\n\n1. Dockerとは：超入門編\n2. Dockerの目的\n\n   * Dockerとは\n   * Dockerでできること\n   * Dockerイメージとは\n   * Dockerコンテナとは\n   * Dockerfileとは\n   * Dockerはなぜ重要なのか\n3. Dockerの主な機能\n\n   * Dockerの特徴\n   * Docker Composeとは\n4. アプリケーションのデプロイにおけるDockerのメリット\n\n   * 開発環境と本番環境のシームレス化\n   * 起動の軽量化・処理速度の高速化\n   * バージョン管理のしやすさ\n   * 優れたスケーラビリティ\n5. Dockerのデメリット\n\n   * ひとつのOSを使わなければならない\n   * 大規模開発時のオーバーヘッド\n   * 技能習得に時間がかかる\n   * セキュリティに脆弱性が生じることもある\n   * コンテナ間での連携が難しい\n6. GitLabはDockerが抱える課題をどのように解決するのか\n7. GitLabのDevSecOpsにおけるDockerの役割\n8. まとめ\n9. FAQ（よくある質問）\n\n## Dockerの目的\n\nはじめに、Dockerとはどういったもので、何ができて、どうして便利なのか、なぜ重要なのか、Dockerの目的に着目しながらその概念をまとめていきます。\n\n### Dockerとは\n\nDockerは、Linuxのコンテナ技術を用いた軽量なソフトウェアコンテナプラットフォームです。アプリケーションの開発、出荷、実行を簡易化するために設計されました。Dockerを使えば、すべての依存関係と一緒にアプリケーションをパッケージ化できるため、依存関係を一つひとつ手動でインストールする必要がなくなり、一貫性のあるコード実行が可能になります。\n\nDockerを使えばアプリケーションの実行環境を標準化でき、環境の違いによる問題を減らすことで開発から本番環境へのデプロイ時間を大幅に短縮できます。\n\nLinuxには以前からコンテナ仮想化という技術がありました。この技術を使うと、プログラムを開発・実行環境から隔離することにより、複数のプログラムを素早く実行できます。ただし、この従来型の仮想化技術は、仮想環境を構築するためにホストとなるOS（オペレーティングシステム）に依存する必要がありました。Dockerはこのコンテナ仮想化技術をOSに関係なく簡単に扱えるようにしたソフトウェアといえます。\n\nDockerの基本概念はイメージとコンテナです。Dockerイメージは、読み取り専用のテンプレートであり、コンテナを作成するための指示が記述されています。たとえば、コンテナで実行するアプリケーションとその依存関係、環境変数、ファイルシステムなどがこれに含まれます。\n\n### Dockerでできること\n\nDockerを使うと、1台のマシン中に複数のコンテナ（仮想環境）をビルドできるため、いくつかの開発環境に対応することができます。つまり、1台のサーバー上で複数のアプリケーションを効率的に動かすことができるのです。アプリケーションの開発環境をDockerで構築すれば、たとえば開発環境（Windows）で動いていたアプリケーションがLinux上で起動しない、といった問題は発生しません。Dockerで構築した環境は、他のデベロッパーとクラウド上で簡単に共有できるため、開発作業がスムーズに進められます。\n\n### Dockerイメージとは\n\nDockerイメージは、アプリケーションを実行するのに必要なソースコードと必要な依存関係をパッケージ化したものです。Dockerコンテナを実行する際には、このDockerイメージが必要です。\n\nDockerイメージは、コンテナイメージを構成する複数のファイルに、`Dockerfile` を合わせてビルドします。つまり、Dockerイメージは、手作業で書くのではなく、コマンドを使って作成します。\n\nそのため、Dockerイメージは単一のファイルではなく、Dockerコンテナの実行に必要なパッケージ（ファイルやメタデータの集合体）であることを理解することが重要です。\n\n### Dockerコンテナとは\n\nLinuxのコンテナは、アプリケーションを内包し、必要なライブラリや依存関係、ファイルが含まれています。\n\n一方、Dockerコンテナは、Dockerイメージの実行可能なインスタンスです。これはDockerイメージから生成され、アプリケーションを実行するためのランタイム環境です。ただし、ハイパーバイザーを使用する従来の仮想化とは違い、DockerのコンテナはホストOS（オペレーティングシステム）のカーネルで実行されます。Dockerイメージ内には、個別のOSはありません。\n\nDockerイメージは環境のスナップショットであり、コンテナはソフトウェアを実行する環境といえます。\n\n### Dockerfileとは\n\n`Dockerfile`は文字情報を主体とするファイルで、ファイルの拡張子はありません。`Dockerfile`には、アプリケーションの構築から実行までのプロセスに必要なコマンドが記述されています。どのファイルをどこから取得して、どんな処理を行ない、Dockerイメージに含めるのかなどを記述します。\n\n`Dockerfile`は、Dockerイメージを作成するためのテキストファイルです。コンテナイメージをビルドする場合も、コンテナのビルド手順を`Dockerfile`で定義する必要があります。この`Dockerfile`には、命令のスクリプトが含まれており、Dockerはコンテナイメージをビルドする際にこのスクリプトを使用します。\n\n### Dockerはなぜ重要なのか\n\nDockerは、コンテナに関する既存のコンピューティングの概念、とりわけLinuxの「cgroups」や「namespaces」、「overlayfs」などの技術を活用しています。これは、アプリケーションの依存関係をサーバーやネットワークなどのインフラストラクチャから隔離したいという、デベロッパーやシステムオペレーターのニーズに応えるものでした。\n\nDockerを使うと、1台のサーバー上でさまざまなアプリケーションを簡単に仮想化・実行できるようになります。さらには、ローカルマシンに依存しない開発環境を実現でき（開発環境の統一）、本番環境に近い環境でのシミュレーションが可能になり、アプリケーションの依存関係も管理できます。加えて、ビルド、テスト、デプロイまでの各プロセスを一貫して行なうことができます。\n\n## Dockerの主な機能\n\nDockerは、Linuxのコンテナ技術を使用しています。Dockerコンテナはよく仮想マシンと比較されます。\n\n仮想マシンでは、ホストマシン上でハイパーバイザーを利用してゲストOSを動かし、さらにその上でミドルウェアやライブラリ、さらにその上にアプリなどを実行します。\n\nそれに対し、コンテナはホストマシンのカーネルを利用し、プロセスやユーザーなどを隔離します。そのため、非常に軽量で、まるで別のマシンが動いているかのように動作します。その結果、アプリなどを高速に起動、停止することが可能です。\n\nDockerは、次の4つの構成要素から成り立っています。\n\n* **Dockerイメージ：** アプリケーション実行に必要なソースコード、アプリと依存関係のパッケージ\n* **Dockerコンテナ：** アプリケーションを実行するランタイム環境\n* **Docker Hub：** クラウド上のレジストリサービス。アプリケーションやサービスコンテナのビルドと配信を行なう\n* **Dockerfile：** Dockerイメージを作成するために実行するコマンドライン命令を含むテキストファイル\n\n### Dockerの特徴\n\nDockerには、次のような特徴があります。\n\n* **軽量かつ高速：** 1つのOSで複数のコンテナを管理でき、仮想マシンより軽量で高速に立ち上げることが可能。\n* **環境の一貫性が保持でき再現性がアップ：** Dockerコンテナは異なるプラットフォームでも一貫して動作するため、ローカル、クラウド、ハイブリッド環境への移行が簡単にできる。\n  移植性が高い －クラウドシステムとの親和性が高く、主要なクラウドプロバイダーはDockerコンテナの実行をサポートしている。\n* **サンドボックスの提供：** セキュリティ対策やソフトウェア開発において、隔離された仮想環境でプログラムを実行・検証できる。このため、ホストマシンの環境を守ることができる。\n* **IaC（インフラストラクチャのコード化）を使用して、インフラをコード化：** Dockerfileによりミドルウェアのインストールや環境設定をコード化して管理できる。\n\n### Docker Composeとは\n\nDocker Composeは、複数のDockerコンテナを一元管理する、 Dockerアプリケーションのためのツールです。YAMLファイルを使用してアプリケーションのサービスを設定します。単一のコマンドで複数のサービスをまとめて生成したり、起動・停止したりすることができます。\n\nDocker Composeのコマンド例は次のとおりです。\n\n* **`docker-compose up`：** サービス用のコンテナを構築、作成、起動、アタッチします。リンクされているサービスがまだ起動していない場合は、それらも起動します。\n* **`docker-compose ps`：** Docker Composeで管理されている稼働中のサービスを一覧表示します。\n* **`docker-compose build`：** Docker Composeファイルで定義されているサービスをビルド（構築）します。\n\n## アプリケーションのデプロイにおけるDockerのメリット\n\nアプリケーションのデプロイにおけるDockerのメリットは次のとおりです。\n\n### 開発環境と本番環境のシームレス化\n\nコンテナ技術の利用を開発環境と本番環境で統一することで、環境の違いにより起こる問題を減らすことができます。その結果、デベロッパーと運用チームとの連携がスムーズに行われ、チーム間で発生していた問題も最小限に抑えられます。\n\n### 起動の軽量化・処理速度の高速化\n\nDockerのコンテナ技術は従来の仮想環境より軽く、アプリを瞬時に起動できます。これは、CPUやメモリなどのコンピュートリソースを必要最低限しか使用しないためです。起動速度が上がることで、開発にも集中できます。\n\n### バージョン管理のしやすさ\n\nDockerでは、GitLabなどのソースコードのバージョン管理ツールを使用できるため、バージョン管理の可視化が進むだけでなく、ロールバックやアップデートも簡単に行なえるようになります。\n\n### 優れたスケーラビリティ\n\nコンテナは軽量で拡張性に優れています。必要に応じて簡単に増減できます。これにより、アプリケーションの拡張やスケーリングを迅速に行なえるため、変わりゆく状況にも柔軟に対応できます。\n\n## Dockerのデメリット\n\nDockerにはさまざまなメリットがありますが、いくつかデメリットも存在します。以下にデメリットを挙げます。\n\n### 1つのOSを使わなければならない\n\nDockerは1つのOS上で複数のコンテナを作成します。これにより起動速度や処理速度の面でメリットがありますが、同時にデメリットになることもあります。たとえば、異なるOS環境で検証をしたい場合には、別のマシンや仮想マシンを準備する必要が生じます。\n\n### 大規模開発時のオーバーヘッド\n\nDocker自体は軽量ですが、大規模システムに拡張する場合には、Dockerの管理に伴う負荷が発生します。Dockerは1台のサーバーで多数のコンテナを実行できますが、その反面、管理やオーケストレーションが必要になり、その処理のためにオーバーヘッドが生じる場合があります。Dockerだけですべての管理を行なうのが困難になることもあります。\n\n### 技能習得に時間がかかる\n\nDockerは他の仮想マシンと異なる手法で仮想環境を構築します。つまり、デベロッパーは新しいコンセプトをすべてゼロから習得しなければならず、それには時間がかかります。Dockerの動作原理をきちんと理解せずに使用すると、あとでトラブルや問題が発生することもあります。Dockerについてしっかりと学習してから運用に取り組むようにしましょう。\n\n### セキュリティに脆弱性が生じることもある\n\nDockerはコンテナ型アーキテクチャです。1台のマシン上で複数のコンテナが動作するため、このことに起因する脆弱性には注意が必要です。たとえば、複数のコンテナがホストOSのリソースやカーネルを共有しているため、一つのコンテナに脆弱性があった場合、全体にその影響が及ぶ可能性があります。\n\n### コンテナ間での連携が難しい\n\n複数のコンテナ間での連携を検討している場合、各種設定が難しいために、運用時に問題が発生することがあります。たとえば、アプリとデータベースを別のコンテナで作成し、一緒に運用したい場合には、同一ホスト内で通信設定をしなければなりません。ポートやソケットを開放する場合にはセキュリティ面でリスクが生じます。それを避けるために設定を複雑にしてしまうと、今度は運用面で問題が起きる恐れがあります。コンテナを連携させる際は、設計段階から十分に検討することが重要です。\n\n## GitLabはDockerが抱える課題をどのように解決するのか\n\nDockerコンテナ内にGitLabをインストールすることができます。[GitLab](https://about.gitlab.com/ja-jp/platform/)は、Git「分散型バージョン管理システム」を主体としたDevSecOpsプラットフォームです。ソフトウェア開発ライフサイクル全体に対応する単一のプラットフォームで、GItLabを活用することで高品質なソフトウェアの迅速なデリバリーを実現できます。\n\nDockerコンテナ内にGitLabをインストールすると、GitLabインスタンスにアクセスできるようになります。Dockerコンテナへの[GitLab Dockerイメージのインストールは公式にサポート](https://about.gitlab.com/ja-jp/install/)されています。\n\nDockerが抱えるいくつかの問題のうち、特にセキュリティについては、GitLabのDevSecOps（開発、セキュリティ、運用）を活用して対処することができます。GitLabのDevSecOpsでは、[シフトレフト](https://about.gitlab.com/ja-jp/topics/ci-cd/shift-left-devops/)を重視しており、セキュリティ対策を開発サイクルの早い段階に組み込むことにより、コンテナイメージの持つセキュリティの問題の早期発見と対応を図っています。継続的インテグレーションによってこのシフトレフトのコンセプトを実践することで、セキュリティ対応にかかっていたコストを削減できます。\n\nDevSecOpsにおいて重要なCI/CDを実現するためには、自動化が欠かせません。GitLabではパイプラインがCI/CDの命令をまとめています。そして、その指示に従いプロセスの自動化を実現するときの基盤になっているのが[GitLab Runner](https://docs.gitlab.com/runner/)（英語）です。GitLab Runnerはセキュリティのシフトレフトを実現する上で重要な役割を果たしています。\n\nGitLab Runnerはセキュリティスキャンやテストを指定したタイミングで自動で実行してくれます。また、レポート作成ジョブを実行して、ダッシュボードに最新情報を表示することも可能です。\n\n## GitLabのDevSecOpsにおけるDockerの役割\n\nGitLabを活用したDevSecOpsインテグレーションにおいても、Dockerは非常に大切な役割を担っています。\n\n### CI/CDジョブのコンテナ化\n\nGitLab CI/CDでは、CI/CDパイプラインでDockerコンテナを使用することで、次のようなことが可能になります。\n\n* **一貫性：** CI/CDジョブはコンテナ内で実行されるため、依存関係や環境の違いによるエラーが防げます。\n* **スケーラビリティ：** コンテナは軽量かつ迅速に起動でき、大規模なパイプラインでも効率的に実行できます。\n* **環境の柔軟性：** ジョブごとに異なるDockerイメージを指定できるため、必要な環境を簡単に準備できます。\n\nGitLab RunnerのDockerイメージは、UbuntuまたはAlpine Linuxをベースにしています。Dockerイメージは標準の`gitlab-runner`コマンドを内包しており、ホストに直接GitLab Runnerをインストールしたかのように動作します。\n\n### セキュリティスキャンの自動化\n\nセキュリティはDevSecOpsでの重要な要素であり、Dockerはこれをサポートします。\n\n* **コンテナイメージのセキュリティスキャン：** GitLabには、CI/CDパイプラインでDockerイメージをスキャンする機能があります。このスキャンにより脆弱性がチェックされ、イメージ内の依存関係やコードの安全性を評価できます。\n* **コンテナ脆弱性スキャンの自動化：** GitLabにはTrivyやAquaなどのセキュリティツールを統合できます。DockerイメージのOSやアプリケーションが最新であるか、既知の脆弱性がないかをチェックします。\n\n### IaC（インフラストラクチャのコード化）と環境管理\n\n* **再現性：** DockerをGitLabのCI/CDジョブ内で使用することで、開発環境と本番環境の整合性を保つことできます。\n* **ステージングやテスト環境を即時に構築：** Docker ComposeやKubernetesと連携することで、特定のブランチやマージリクエストごとに分離された環境をGitLabで作成できます。これにより、テストやセキュリティスキャンを効率的に実行できます。\n\n### デプロイの効率化\n\nGitLabは、Dockerを使用する以下のデプロイパターンをサポートしています。\n\n* **Dockerイメージのビルドとプッシュ：** アプリをコンテナイメージとしてビルドして、GitLabのContainer Registryや他のDockerレジストリにプッシュします。\n* **継続的デリバリー：** Dockerイメージを使ってコンテナオーケストレーションツールにデプロイすることで、迅速で安全なリリースが可能になります。\n\n### マイクロサービスアーキテクチャのサポート\n\nGitLabとDockerを組み合わせることで、マイクロサービスアーキテクチャを簡単に構築できます。マイクロサービスは別々のDockerコンテナとして実行します。GitLab CI/CDパイプラインを使うと、以下のことを管理できます。\n\n* サービス間の依存関係の設定\n* 個別のセキュリティスキャン\n* バージョン管理（ロールバックが容易になります）\n\n## まとめ\n\n2013年の公表以来、Dockerは瞬く間にIT業界に広く普及しました。本記事では、Dockerの基本概念、基本技術、Dockerを使って何ができるのか、なぜDockerが重要なのか、Dockerを理解上でよく目にする用語などについて紹介してきました。\n\nDockerを使う場合には、DevSecOpsにとって大切なCI/CDを実現するためにも、GitLab CI/CDなどの自動化ツールの導入をおすすめします。GitLab のCI/CDパイプラインでDockerコンテナを使用することで、開発における一貫性の維持、スケーラビリティの実現、柔軟な環境の準備が可能になります。\n\n## FAQ（よくある質問）\n\n### Dockerで何ができるのか？\n\nDockerコンテナは、軽量でスタンドアロンの仮想化技術であり、アプリケーションコード、その依存関係、ライブラリをすべてパッケージ化します。Dockerを使うと、1台のマシン上に複数のコンテナ（仮想環境）を構築でき、開発環境や検証環境の統一が図れます。詳しくは、記事の本文をご覧ください。\n\n### Dockerは何に使うのか？\n\nDockerは、デベロッパーがアプリケーションとその依存関係をシステムから切り離したいとき使用します。コンテナにはアプリケーションとその依存関係がまとめられており、軽量な実行環境を提供します。詳しくは、記事の本文をご覧ください。\n\n### Dockerコンテナとは何ですか？\n\nDockerイメージが実行時にコンテナになります。Dockerコンテナは、アプリケーションを実行するためのランタイム環境です。Dockerコンテナに関する詳細は、記事の本文をご覧ください。\n\n*監修：川瀬 洋平 [@ykawase](https://gitlab.com/ykawase)*\n\n*（GitLab合同会社 カスタマーサクセス本部 シニアカスタマーサクセスマネージャー）*","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750226168/pf5cwmvqq09v1pe0re66.jpg",[111,678,679,680,681,682,683,684],"cloud native","DevOps","DevSecOps","features","performance","security","tutorial",{"featured":93,"template":686,"slug":687},"BlogPost","what-is-docker","content:ja-jp:blog:what-is-docker.yml","What Is Docker","ja-jp/blog/what-is-docker.yml","ja-jp/blog/what-is-docker",[693,719,739,759,778,802,821,844,864,886,910,931,951,974],{"_path":694,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":695,"content":703,"config":713,"_id":715,"_type":16,"title":716,"_source":18,"_file":717,"_stem":718,"_extension":21},"/ja-jp/blog/what-is-kubernetes",{"title":696,"description":697,"ogTitle":696,"ogDescription":697,"noIndex":6,"ogImage":698,"ogUrl":699,"ogSiteName":700,"ogType":701,"canonicalUrls":699,"schema":702},"Kubernetes（K8s）とは？その仕組みから利点、使い方まで","Kubernetes（K8s）とは？Kubernetes の読み方から覚えておきたい用語、仕組みやその利点について学びましょう。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687485/Blog/Hero%20Images/kubernetes.jpg","https://about.gitlab.com/blog/what-is-kubernetes","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Kubernetes（K8s）とは？その仕組みから利点、使い方まで\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Japan Team\"},{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-04-28\",\n      }",{"title":696,"description":697,"authors":704,"heroImage":698,"date":707,"body":708,"category":14,"tags":709},[705,706],"GitLab Japan Team","GitLab","2025-04-28","## 目次\n\n1. Kubernetesとは？その読み方と用途\n2. Kubernetes（K8s）の基本用語解説\n  - コンテナ、Pod、Node、クラスター\n  - Dockerとの違い\n3. Kubernetesの主な特徴\n  - デプロイの自動化\n  - ハイブリッド / マルチクラウドに対応\n  - 拡張性とプラグインアーキテクチャ\n  - ローリングアップデートとロールバック\n  - 柔軟なスケーラビリティ\n  - リリース後のアプリケーション監視\n4. Kubernetesの利点とは\n  - 生産性の向上\n  - 自己修復機能により障害に耐性\n  - 高い可用性を担保\n  - オンプレミスでも、クラウドでも運用可能\n  - 大量のコンテナを一括管理\n  - DevSecOpsとの親和性が高い\n  - クラウドネイティブなワークロードを安全に保つ\n5. GitLabでKubernetesを統合する\n6. Kubernetes（K8s）のよくある質問\n  - KubernetesとDockerの違いは何ですか？\n  - Kubernetesで何ができますか？\n  - Kubernetesコンテナとは何ですか？\n  - Kubernetesの読み方は？\n\n## Kubernetesとは？その読み方と用途\n\nKubernetesは、「クバネティス」、「クーベネティス」、または「クーバネーティス」と発音します。ギリシャ語のκυβερνήτηςに由来し、「統治者」や「パイロット」といった意味を持ちます。また、K8sと表記されることもあります。  \n\nKubernetesは、一言で表せばソフトウェア開発においてコンテナを操作・管理するもので、コンテナオーケストレーションの役割を果たすオープンソースソフトウェアとして開発されました。Kubernetesは、クラウドネイティブのプログラムの開発に使用します。これを使用することで[マイクロサービス](https://about.gitlab.com/ja-jp/topics/microservices/)アーキテクチャが可能になり、プログラムの開発が高速化できます。  \nでは、Kubernetesについて、もう少し掘り下げて見ていきましょう。\n\n## Kubernetes（K8s）の基本用語解説\n\n### コンテナ、Pod、Node、クラスター\n\nKubernetesは、コンテナをオーケストレーションするためのツールです。オーケストレーションとは、複数のコンピュータシステムやアプリケーション、サービスなどを調整して管理し、頻繁に繰り返される大規模なワークフローやプロセスを実行できるようにすることを指します。では、コンテナとは何でしょう。ソフトウェア開発におけるコンテナ化とは、ソフトウェアのコードをライブラリやフレームワークなどの依存関係にあるすべてのコンポーネントとともにパッケージ化し、それぞれの入れ物、「コンテナ」に隔離することを意味します。コンテナは、完全に機能するポータブルなコンピューティング環境です。また、このコンテナを複数まとめたものがPod、PodをまとめたものがNode、Nodeをまとめたものがクラスタと呼ばれます（以下の図を参照）。\n\n![kubernetesとは](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687494/Blog/Content%20Images/kubernetes-diagram.svg)\n\n*Kubernetesにおけるコンテナとクラスタの関係を示した図*\n### Dockerとの違い\n\nKuberunetesはコンテナオーケストレーションツールですが、Dockerはコンテナ化ツールの1つです。Dockerはアプリケーションのコンテナ化を行なうとき使用するプラットフォームです。仮想マシンよりも軽量で高速であることや、環境構築が簡単なことから、コンテナ化の主流ツールになっています。\n\n## Kubernetesの主な特徴\n\nKubernetesは、前述したようにコンテナを管理するコンテナオーケストレーションツールで、代表的な機能としては次のようなものが挙げられます。\n\n### デプロイの自動化\n\nKubernetesは、アプリケーションのデプロイ時に、新しいコンテナの作成や既存コンテナの削除を自動で実施します。また、新しく作成したコンテナにも自動でリソースを適用します。\n\n### ハイブリッド / マルチクラウドに対応\n\nクラウドプロバイダーに依存することなく、オンプレミス環境や様々なクラウドサービス（AWS、Azureなど）上で動作します。よって、ハイブリッドクラウドやマルチクラウド環境を簡単に構築、管理することができます。\n\n### 拡張性とプラグインアーキテクチャ\n\n多様なプラグインや拡張機能が利用できます。例えば、CustomResourceDefinitions（CRD）を使って新規にリソースタイプやロジックを追加したり、CNI（Container Network Interface）やCSI（Container Storage Interface）といったプラグインでネットワークやストレージのカスタマイズが可能です。\n\n### ローリングアップデートとロールバック\n\nKubernetesでは、アプリケーションのバージョンを更新する際、ローリングアップデートがそのデフォルトとなります。また、ビルトインでロールバック機構もあります。このため、ライブトラフィックに影響を与えず、ダウンタイムゼロでデプロイを実現できます。\n\n### 柔軟なスケーラビリティ\n\nKubernetesは、大量のコンテナを効率的に管理するためのもので、システムのスケーラビリティが向上できます。スケーラビリティとは、どのくらいシステムの拡張ができるかを示す特性で、Kubernetesではコンテナ化されたアプリケーションの数を増減することでスケーリングします。\n\n### リリース後のアプリケーション監視\n\nPrometheusやGrafanaといった監視ツールを使用することで、アプリケーション固有のメトリクスが監視できます。リリース後のパフォーマンス低下や不具合発見といった事象がアラートされるため、問題に迅速に対処できます。\n\n## Kubernetesの利点とは\n\nKubernetesには次のような7つのメリットがあります。\n\n### 生産性の向上\n\n一つ目のメリットは、アプリケーション開発で生産性が向上できる点にあります。従来の仮想化では、アプリケーションごとにゲストOSを用意する必要がありましたが、Kubernetesでは、アプリケーションを直接コンテナエンジン上にデプロイできるため、サーバーのリソース使用量が抑えられます。\n\n### 自己修復機能により障害に耐性\n\nKubernetesには、PodやNodeに障害が起きた場合、最初の定義（マニフェスト）の状態まで自動修復する機能が備わっています。\n\n### 高い可用性を担保\n\nKubernetesは、複数のNodeの集まりであるクラスターを構成します。あるクラスターで障害が発生した場合、障害が起きたコンテナを自動で再起動させます。また、他のNodeでコンテナを起動させ、処理を引き継ぐ動作も継続できるため、高い可用性が担保できます。\n\n### オンプレミスでも、クラウドでも運用可能\n\nKubernetesは、オンプレミスでも、プライベートクラウド、パブリッククラウドでも利用できます。つまり、自社サーバーでも、クラウドを使っても、どんな環境でも運用可能です。\n\n### 大量のコンテナの一括管理\n\nKubernetesでは、大量のコンテナが一括で管理・運用できます。また、設定ファイルを複数のコンテナ間で共有することによって、設定変更時も正確かつ大量に設定を反映させることが可能です。\n\n### DevSecOpsとの親和性が高い\nDevSecOpsとは、開発と運用を統合するDevOpsにセキュリティを加え、運用を視野に入れながら開発とセキュリティを同時に進め、安心・安全なソフトウェアを迅速にリリースするというコンセプトです。Kubernetesにはアプリケーションの開発と運用の双方に必要とされる機能が多く搭載されているため、DevSecOpsとの親和性が非常に高いという特長があります。\n\n### クラウドネイティブなワークロードを安全に保つ\n\nKubernetesは、クラウドネイティブアーキテクチャに基づいており、クラウドネイティブな情報セキュリティに関するベストプラクティスについて、CNCF（Cloud Native Computing Foundation）からのアドバイスを活用しています。\n\nたとえばKubernetesには、APIやセキュリティコントロールが含まれており、情報セキュリティを管理するポリシーを定義する手段も備わっています。クラウドの利用などでセキュリティ面において懸念が生じても、Kubernetesならユーザーごとにアクセス制限を設定でき、不正アクセスが防止できるため安心です。\n\nまた、Pod Security Standardによりセキュリティに3つのポリシーが定義されています。非常に緩いものから非常に厳しいものまで累積的に定義できます。\n\n## GitLabでKubernetesを統合する\n\nKubernetesクラスターとGitLabを接続すると、アプリの開発・デプロイ・管理・監視ができます。  \nGitLabをKubernetesと連携させる、またはKubernetes内で動作させるには、3つの異なる方法があります。単独で使用することも、組み合わせて使用することもできます。\n\n* GitLabからKubernetesにソフトウェアをデプロイする  \n* Kubernetesを使用してGitLabインスタンスに紐づいたRunnerを管理する  \n* GitLabのアプリケーションとサービスをKubernetesクラスター上で実行する\n\nさらに詳しい情報やお問い合わせは[こちら](https://about.gitlab.com/ja-jp/solutions/kubernetes/)をご覧ください。\n\n## Kubernetes （K8s）のよくある質問\n\n### KubernetesとDockerの違いは何ですか？\n\nDockerはコンテナ化ツールのひとつで、アプリケーションコンテナを構築し、アプリケーションの開発・配布・実行をします。Kubernetesは、より大規模に複数のマイクロサービスを管理するのに使われます。  \nまた、Kubernetesはクラスターで実行され、Dockerはノードで実行されます。Kubernetesの使用目的はコンテナ管理ですが、Dockerの使用目的の一つは、アプリケーションをコンテナに分離することになります。\n\n### Kubernetesで何ができますか？\n\nKubernetesでできることの代表例には下記のようなものが挙げられます。\n\n* 大量のコンテナの一括管理\n* 起動を含めた動作の高速化・軽量化  \n* 自動デプロイ  \n* 自己修復機能により障害に耐性\n* 高い可用性を担保\n* オンプレミスでも、クラウドでも運用可能\n* DevSecOpsとの親和性が高い\n* クラウドネイティブなワークロードを安全に保つ\n\n### Kubernetesコンテナとは何ですか？\n\nソフトウェアのコードをライブラリやフレームワークなどの依存関係にあるすべてのコンポーネントとともにパッケージ化し、それぞれの入れ物、「コンテナ」に隔離することをコンテナ化と言います。Kubernetesコンテナは、完全に機能するポータブルなコンピューティング環境で、さまざまなプラットフォームでデプロイ可能なプログラムとして[マイクロサービス](https://about.gitlab.com/blog/what-are-the-benefits-of-a-microservices-architecture/)アーキテクチャを可能にします（リンクは英語版です）。\n\n### Kubernetesの読み方は？\n\nKubernetesは、「クバネティス」、「クーベネティス」、または「クーバネーティス」と読み、「K8s（ケーエイツ）」と略されます。\n",[710,678,679,111,535,711,683,682,712],"kubernetes","open source","workflow",{"slug":714,"featured":93,"template":686},"what-is-kubernetes","content:ja-jp:blog:what-is-kubernetes.yml","What Is Kubernetes","ja-jp/blog/what-is-kubernetes.yml","ja-jp/blog/what-is-kubernetes",{"_path":720,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":721,"content":727,"config":733,"_id":735,"_type":16,"title":736,"_source":18,"_file":737,"_stem":738,"_extension":21},"/ja-jp/blog/what-is-yaml",{"title":722,"description":723,"ogTitle":722,"ogDescription":723,"noIndex":6,"ogImage":724,"ogUrl":725,"ogSiteName":700,"ogType":701,"canonicalUrls":725,"schema":726},"拡張子YAMLファイルとは？基本から使い方まで徹底解説","YAMLは構成ファイル紹介などに使用されるフォーマットです。この記事では、YAMLの基本からKubernetesなどでの具体的な使い方まで解説します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662547/Blog/Hero%20Images/what_is_yaml.jpg","https://about.gitlab.com/blog/what-is-yaml","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"拡張子YAMLファイルとは？基本から使い方まで徹底解説\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Japan Team\"},{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-04-09\",\n      }",{"title":722,"description":723,"authors":728,"heroImage":724,"date":729,"body":730,"category":14,"tags":731},[705,706],"2025-04-09","## 目次\n\n- YAMLとは？\n- YAMLを何に使う？\n- YAMLとYMLの違いとは？\n- YAMLとJSONの違い\n- YAMLとCUEの比較\n- YAMLのデータ構造と書き方（基本編） \n- GitLabでYAMLを使う\n- 実際にYAMLファイルを編集してみましょう\n- YAMLに関するFAQ\n\nYAMLは、[Kubernetes](https://about.gitlab.com/ja-jp/blog/what-is-kubernetes/)ファイルやAnsibleプレイブックに使用されるデータシリアライゼーション・フォーマットです。この記事では、YAMLファイルの基本的な書き方や具体的な利用シーンについて詳しく解説します。\n\n## YAMLとは？\n\nYAMLは、人間がデータを簡潔かつ理解しやすく表現するよう設計されており、設定ファイルやデータ転送で頻繁に使用されるプログラミング言語です。階層的情報の整理に適し、Jsonやxmlの代替と利用されることがあります。\n\n## YAMLを何に使う？\n\nYAMLは可読性の高いこともあり、設定ファイルやプレイブックの記載に使われます。いくつか例を下記に記載しますので、参考にしてください。\n\n* 設定ファイルの記述  \n* ログファイル  \n* プロセス間でのメッセージのやり取り  \n* アプリケーション間でのデータ共有  \n* 構造化データの記述\n\n## YAMLとYMLの違いとは？\n\nどちらも同じ形式のファイルを指し、拡張子が「.yml」か「.yaml」という表記の違いだけです。ヤムルファイルであることを示す正式な拡張子は.yamlですが、一般的に拡張子（.txt, .zip, .exe, .png等）は3文字で記載されるので、この3文字ルールに合わせたのが.ymlとなっています。短く簡潔に書きたい開発者には「.yml」が選ばれることが多いです。\n\n## YAMLとJSON形式の違い\n\nJSON形式では中括弧を使って要件を定義していくのに対して、YAMLは、インデントで構造が明示されるので、可読性が高くなっています。下記サンプルを見比べてください。  \nYAMLは、プログラマーにとっての使いやすさを重視していることがわかると思います。\n\nYAML：  \n![yamlのキーとバリューの記載例](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687456/Blog/Content%20Images/yaml-coding-sample-01.png)\n\nJSON:\n\n![JSON形式のキーとバリューの記載例](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687456/Blog/Content%20Images/json-format-coding-sample-01.png)\n\n## YAMLとCUEの比較\n\nYAMLは、可読性が高くシンプルな構造を持つのに比べ、CUEは、スキーマとデータを統合するため、複雑な設定もひとつのファイルで管理できます。また、YAML単体では実現できなかったスキーマバリデーション機能を持つので、データの整合性を担保しやすいです。\n\nまた、柔軟性も大きな特徴です。CUEは、あらゆる種類のデータを定義、生成、検証するために使用されるオープンソースの言語（具体的にはJSONのスーパーセット）なので、Go、JSON、OpenAPI、Protocol Buffers、YAMLなどの他の多くの言語と連携できます。\n\nまた、Go APIによるスクリプト機能を備えているので、CUEによるマニフェストを最終的な[Kubernetes](https://about.gitlab.com/ja-jp/blog/what-is-kubernetes/)リソースのYAMLとして表示したり、特定クラスタにデプロイするリソースを一覧するコマンドを実装する際などに使う機会があります。\n\n## YAMLのデータ構造と書き方（基本編）\n\n### YAMLファイル記述の注意点\n\nインデントとタブが、とても重要であることを覚えておいてください。余分なインデントやタブが使われていると、YAMLオブジェクトの意味が変わってしまうので、これらがとても重要になります。\n\n### YAMLのデータ構造\n\nYAMLは主に、コレクションとスカラーという２つのデータで成り立っています。コレクションは、シーケンスとマッピングから成り立ちます。シーケンスは配列、マッピングは名前と値のペア（Key : Valueで表現する配列）。そしてスカラーは、型を判別させるためのもので、文字列、数値などを表します。\n\n* コレクション  \n  * シーケンス  \n  * マッピング  \n* スカラー\n\n### YAMLの書き方\n\n![image2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687456/Blog/Content%20Images/image2.png)\n* 複数行のコレクション：複数の行のフォーマットを維持する必要がある場合には | (バーティカルバー) シンボルを使用します。  \n* 複数行のフォーマット：長い文字列の値があり、フォーマットを維持したまま複数行に渡って記述する必要がある場合には、 \\> を使用します。  \n* リスト：リストは \\- （ハイフン）を使って表現します。  \n* ネスト：ネストされたデータ構造はインデントを使って表現されます。\n\n### Kubernetes（k8s)のYAMLファイルの書き方\n\nKubernetesでは、リソースの定義にYAMLファイルが使用されます。今回はYAMLマニフェストの書き方を紹介します。  \n\nYAMLマニフェスト：  \n![YAMLでKubernetesのマニフェストの書き方例](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687456/Blog/Content%20Images/YAML-manufest-sample-Kubernetes.png)\n\n### AnsibleのYAMLファイルの書き方\n\nAnsibleでは、処理内容を記載するプレイブックをYAMLで記載します。以下に、簡単なAnsibleプレイブックの例を示します。\n\n![image3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687457/Blog/Content%20Images/image3.png)\n\n## GitLabでYAMLを使う\n\nGitLab CI/CD パイプラインは、プロジェクト毎に[.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/examples/index.html)というYAMLファイルを使って[パイプラインの構造と実行順序を定義](https://gitlab.com/stylez-co-jp/gitlab-ce/-/blob/dev-v12.0.3-ja.1/doc-ja/ci/yaml/README.md)します。このファイルで設定された内容を、GitLab Runnerの中で処理します。CI/CD YAML構文については[こちらの英文まとめページ](https://docs.gitlab.com/ee/ci/yaml/)をご参照ください。\n\n## 実際にYAMLファイルを編集してみましょう\n\nYAMLは、そのシンプルさと可読性の高さから、設定ファイル、CI/CDパイプライン、Kubernetesをはじめとするコンテナオーケストレーションやドキュメント、構成管理など、多岐にわたり利用されています。その可読性の高さで、開発者や運用エンジニアが構成やデータを容易に管理し、効率的に作業を進めることができます。YAMLを理解することで、様々なシステムやツールの設定がより簡単かつ直感的に行えるようになるでしょう。\n\n## YAMLに関するFAQ\n\n### YAMLは何に使われますか\n\nYAMLは、そのシンプルさと可読性の高さから、設定ファイル、CI/CDパイプライン、Kubernetesをはじめとするコンテナオーケストレーションやドキュメントと構成管理など、多岐にわたり利用されています。\n\n### YAMLとJSONの違いは？\n\nJSONファイルは中括弧を使って要件を定義していくのに対して、YAMLは、インデントで構造が明示されるので、可読性が高くなっています。ただし、YAMLではインデントやスペースがとても重要になる点に注意が必要です。\n\n### YAMLはなぜ人気なのですか？\nYAMLは開発者の間で人気のあるデータシリアライズ言語です。なぜなら、その読みやすさ、汎用性、Pythonと似たインデントシステムを使うからです。YAMLは複数のデータ型をサポートしており、多くのプログラミング言語で利用可能なパーサーライブラリが提供されているため、さまざまなデータシリアライゼーションタスクを扱うことができ、幅広い場面で活用されています。\n\n\u003Cbr>\u003Cbr>\n\n*監修：佐々木 直晴 [@naosasaki](https://gitlab.com/naosasaki) （GitLab合同会社 ソリューションアーキテクト本部 シニアソリューションアーキテクト）*",[679,710,680,111,535,678,684,712,711,732],"git",{"slug":734,"featured":93,"template":686},"what-is-yaml","content:ja-jp:blog:what-is-yaml.yml","What Is Yaml","ja-jp/blog/what-is-yaml.yml","ja-jp/blog/what-is-yaml",{"_path":740,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":741,"content":747,"config":753,"_id":755,"_type":16,"title":756,"_source":18,"_file":757,"_stem":758,"_extension":21},"/ja-jp/blog/what-is-agile-development",{"title":742,"description":743,"ogTitle":742,"ogDescription":743,"noIndex":6,"ogImage":744,"ogUrl":745,"ogSiteName":700,"ogType":701,"canonicalUrls":745,"schema":746},"アジャイル開発とは？意味や進め方、DevSecOpsとの関係性を解説","この記事では、アジャイル開発の概要やウォーターフォール開発との違い、導入するメリット・デメリットなどを解説します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663632/Blog/Hero%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA7.jpg","https://about.gitlab.com/blog/what-is-agile-development","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"アジャイル開発とは？意味や進め方、DevSecOpsとの関係性を解説\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Japan Team\"},{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-03-06\",\n      }",{"title":742,"description":743,"authors":748,"heroImage":744,"date":749,"body":750,"category":14,"tags":751},[705,706],"2025-03-06","アジャイル開発はシステム・ソフトウェア開発手法のひとつであり、近年注目されています。実際に自社の開発課題を解決するために、アジャイル開発の導入を検討している担当者は多いのではないでしょうか。\n\nこの記事では、アジャイル開発の概要やウォーターフォール開発との違い、導入するメリット・デメリットなどを解説します。アジャイル開発におけるAI活用や、[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)の関係性についても触れているのでぜひ参考にして下さい。\n\n## アジャイル開発とは？\n\n![アジャイル開発2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687637/Blog/Content%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA2.jpg)\n\nアジャイル開発とは、ソフトウェア開発において通常1週間から4週間程度の反復期間を設定し、企画から開発、テストまでの工程を機能単位ごとに繰り返し進めていく開発手法のことです。「アジャイル」という言葉には、「素早い」「機敏な」という意味があり、その言葉の通りアジャイル開発はスピード感のある開発が可能です。\n\n近年ビジネス環境の変化が激しく、日々変化するニーズや市場に柔軟に対応していく姿勢が必要です。アジャイル開発ならスピード感を持って開発を進められるだけでなく、仮説検証を含めた柔軟な開発が可能になります。\n\n物事の予測が立てにくい不確実な要素が多い時代の中で、顧客ニーズにマッチした新しい価値を創造するための手法としてアジャイル開発が注目されているのです。\n\n## アジャイルソフトウェア開発宣言とは？\n\n「アジャイルソフトウェア開発宣言」とは、17名のソフトウェア開発者が議論を行なって文書としてまとめたアジャイル開発の原則のことです。\n\n2001年に公開されたことをきっかけに、世界中にアジャイル開発の考え方が広まり、多くのソフトウェア開発者達に支持されました。\n\nアジャイルソフトウェア宣言では、アジャイル開発を実現するために以下の4つの価値を示しています。\n\n1. プロセスやツールよりも「個人と対話」  \n2. 包括的なドキュメントよりも「動くソフトウェア」  \n3. 契約交渉よりも「顧客との協調」  \n4. 計画に従うことよりも「変化への対応」\n\n※出典：[アジャイルソフトウェア開発宣言](https://agilemanifesto.org/iso/ja/manifesto.html)\n\n## アジャイル開発とウォーターフォール開発との違い・比較\n\n![アジャイル開発5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687637/Blog/Content%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA5.jpg)\nアジャイル開発が登場する前にはウォーターフォール開発が主に活用されており、ソフトウェア開発の初期段階として位置付けられています。\n\nウォーターフォール開発は機能単位ごとに開発工程を繰り返すアジャイル開発とは異なり、開発前に全ての機能計画を立て、その計画通りに開発を進める手法になります。つまり、要件定義から設計、実装、テスト、運用といった各工程を順序立てて直線的に開発を進めていきます。\n\n開発対象の機能を事前に決定して開発を進めるため、最終的なリリース時期がわかりやすいというメリットがあります。一方、開発前から全ての工程が決まっているため、仕様変更がしにくいなどの課題もあります。\n\n## アジャイル開発でよく採用されている手法とは？\n\nアジャイル開発にはさまざまな開発手法がありますが、中でも「スクラム」と呼ばれる開発手法が最も採用されています。スクラムとは、少人数のチームにわかれて密にコミュニケーションをとりながら開発を進める手法です。\n\n実際に「[17th State of Agile Report](https://digital.ai/resource-center/analyst-reports/state-of-agile-report/)」の調査では、アジャイル開発手法の中で、63%がスクラムを採用していると報告されています。なお、スクラムの人気は2006年の最初の調査以降続いています。\n\nなぜ数ある開発手法の中でスクラムが最も採用されるのでしょうか。理由のひとつとして汎用性の高さにあると考えられます。スクラムはシンプルなフレームワークであり、さまざまな開発プロジェクトに活用することが可能です。\n\nまた、スクラムのルールが示された「[スクラムガイド](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)」は、18ページ程度の少なめのボリューム感となっており、内容もシンプルです。そのため、スクラムの全体の流れや仕組みについて理解がしやすく、自社の開発プロジェクトに合わせて応用がしやすいといえます。\n\nさらに、スクラムは有名な手法であることから開発事例も多く、情報収集が容易であるという事情も採用される理由として挙げられます。\n\n## アジャイル開発の流れ\n\nアジャイル開発はどのような流れで進められるでしょうか。IPAの「[アジャイル開発の進め方](https://www.ipa.go.jp/jinzai/skill-standard/plus-it-ui/itssplus/ps6vr70000001i7c-att/000065606.pdf)」を参考にスクラムを例に全体の流れを紹介します。\n\n1. プロダクトバックログの作成  \n2. スプリントプランニングの実施  \n3. 開発作業の実施\n\n### 1. プロダクトバックログの作成\n\nまずプロダクトバックログの作成を行います。プロダクトバックログとは、開発したいプロダクトが提供する価値をまとめたリストのことです。具体的には、顧客が求める機能やユーザーエクスペリエンスなどを洗い出してリストを作成していきます。\n\nこの際、リストは作業の優先順位をつけて並んでいることがポイントです。また、作成するリストは顧客を含むプロジェクトの関係者全員に共有する必要があるため、誰もが理解できる言葉で記載しなければなりません。\n\n### 2. スプリントプランニングの実施\n\n「スプリント」とは、スクラムにおける開発工程の反復（作業）期間のことです。スプリントが開始される前にスプリントプランニングを実施しましょう。具体的には、作成したプロダクトバックログのリストの中から対象のスプリントで扱う項目を選び出します。ここで選び出した項目は「スプリントバックログ」と呼ばれます。\n\nその後細かにタスクに落とし込み、スクラムチーム内で作業を分担します。なお、各タスクにおいては一般的に2〜8時間程度の時間単位で見積もられます。\n\n### 3. 開発作業の実施\n\n実際にスプリント内の開発作業を実施します。スプリントの途中では、スクラムチーム内で活動状況を報告する「デイリースクラム」が行われます。デイリースクラムは、達成すべきゴールに向けて課題になっていることを共有し、チーム全員が協力して解決を目指すためのミーティングです。\n\n無事にスプリントが完了した段階では「スプリントレビュー」と呼ばれるミーティングが開催され、関係者全員で完成したプロダクトのデモンストレーションを行います。\n\nまた、スプリントレビューの後には「スプリントレトロスペクティブ」が行われ、開発におけるプロセスを振り返ります。うまくいかなかったことは改善策を洗い出し、次のスプリントに活かします。\n\n## アジャイル開発のメリット\n\n![アジャイル開発6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687637/Blog/Content%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA6.jpg)\nアジャイル開発には以下のようなメリットがあります。\n\n* 開発スピードが早い  \n* ユーザーのニーズを反映しやすい  \n* 手戻りの発生を防止・軽減しやすい  \n* 継続的な学習と改善の機会が得られる\n\n### 開発スピードが早い\n\nアジャイル開発は機能を小さな単位にわけて開発とリリースを繰り返して進めるため、結果的に優先度の高い機能から素早く価値を提供することが可能です。また、最初にプロダクトの全ての機能計画を立ててから開発するわけではないため、本来不要だった機能に関するドキュメント作成などに時間と手間をかけずに開発を進められます。\n\n一方、ウォーターフォール開発の場合は計画を重視することから、開発前に要件定義書や設計書などの作成に時間をかける必要があります。ビジネスにおいて「競合優位性を確立したい」「早期に顧客のフィードバックを収集したい」などの目的があるなら、小さな単位で素早く価値を提供できるアジャイル開発の採用が適切だといえます。\n\n### ユーザーのニーズを反映しやすい\n\nアジャイル開発は小さな単位で開発を進めるため、開発途中で顧客の要望や市場の変化に応じて優先順位や仕様を見直すことができます。顧客ニーズや市場調査の結果を踏まえながら柔軟に開発を進めることで最大限の価値を提供できるため、顧客満足度の向上にもつながります。\n\n一方、ウォーターフォール開発ではプロジェクトの初期段階で計画を確定させるため、途中での変更が困難になりがちです。ただし、アジャイル開発で変更に対応できるといっても、変更自体のコストや影響度は慎重に評価する必要があります。\n\n例えば、すでに開発した機能に大きな変更が必要な場合は、再設計や再実装のコストが発生します。アジャイル開発は変更を受け入れやすい仕組みを持っていますが、それは全ての変更が容易であることを意味するわけではありません。\n\n### 手戻りの発生を防止・軽減しやすい\n\nアジャイル開発は機能単位に区切って開発からテスト、リリースまで実行するため、テストの段階で不具合や問題が発生した場合でも手戻りの工数を最小限に抑えられます。\n\nウォーターフォール開発の場合は、事前に決めた計画通りに開発を進めるため、不具合が発生した箇所によっては手戻りの工数が大きくなってしまうデメリットがあります。アジャイル開発なら、前提として開発している範囲が少ないため、大きな手戻りが発生しにくいです。\n\n### 継続的な学習と改善の機会が得られる\n\nアジャイル開発では、小さな単位での開発を繰り返し、振り返りを行うプロセスが組み込まれています。これにより、チームは実践と改善を重ねながら学習を進める機会を得られます。例えば、スプリントごとの振り返り（スプリントレトロスペクティブ）では、うまくいったことや課題を議論し、より良い進め方を模索します。\n\nまた、開発途中では毎日ミーティングが実施され、品質の高いプロダクトを生み出せるようメンバー同士が意見を出し合います。そのようなプロセスを通してチームワークの向上も期待できるでしょう。\n\n## アジャイル開発のデメリット\n\n![アジャイル開発4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687637/Blog/Content%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA4.jpg)\nアジャイル開発にはデメリットもあるため、対策を踏まえて把握しておくことが大切です。\n\n* 長期的な見通しの立て方が従来と異なる  \n* プロダクトの方向性を維持するための工夫が必要\n\n### 長期的な見通しの立て方が従来と異なる\n\nアジャイル開発では、詳細な計画を前もって確定させない代わりに、反復的な開発を通じて計画を継続的に見直し、調整していきます。そのため、従来のウォーターフォール型開発のように、プロジェクト全体の詳細なスケジュールを初期段階で確定することは難しくなります。また、顧客の要望で何度も仕様変更が発生した場合、最終リリースまでのスケジュールが伸びてしまう可能性もあります。\n\nアジャイル開発において適切なスケジュール管理を行うためには、チームの開発速度を計測、定期的に計画と実績を比較し、場合によっては優先順位や計画を見直す必要があります。\n\n### プロダクトの方向性を維持するための工夫が必要\n\nアジャイル開発では、開発途中での変更を受け入れやすい特徴がある一方で、その柔軟性を適切にコントロールしなければ、本来目指していたプロダクトの方向性から逸れてしまうリスクがあります。\n\n例えば、顧客からの仕様変更や機能追加の要望を受け入れ過ぎていると、プロジェクト全体の方向性を見失ってしまう場合があります。また、顧客との摩擦や齟齬が生まれてしまう可能性もあり、プロジェクトがスムーズに進まないという事態も招いてしまうでしょう。\n\nこのようなことを避けるためには、個々の単位だけでなく定期的な全体像の把握と、関係性全員での認識の擦り合わせが必要です。\n\n## アジャイル開発が向いている・向いていないプロジェクト\n\nアジャイル開発にはさまざまなメリットがありますが、プロジェクトの特性・内容によっては向き・不向きがあるため事前に把握し、自社に適した開発手法を採用しなければなりません。\n\nアジャイル開発は柔軟に開発を進められるメリットがあるため、ニーズが漠然としていたり、状況の変化が想定されていたりするケースに向いています。また、発注者が積極的に関わる案件なら、頻繁にフィードバックを受けやすいアジャイル開発の強みを十分に活かせるでしょう。\n\n反対に、要件が明確で大きな変更が想定されず、納期の厳守を求められる場合は、アジャイル開発の採用には慎重な検討が必要といえます。また、開発メンバーと発注者との間でコミュニケーションがとりにくいケースでアジャイル開発を採用しても、開発がスムーズに進まない可能性が高いため別の手法を検討するのが良いでしょう。\n\n## アジャイル開発を成功させるためのポイント\n![アジャイル開発8](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687637/Blog/Content%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA8.jpg)\n\nアジャイル開発を成功させるために以下のポイントを押さえておきましょう。\n\n* アジャイル開発の特性を理解した人材を選定する  \n* メンバー間で密にコミュニケーションをとる  \n* [CI/CD](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)など自動化のテクノロジーを取り入れる  \n* 情報の透明性を保つ\n\n### アジャイル開発の特性を理解した人材を選定する\n\nアジャイル開発では、柔軟な仕様変更に伴うメンバー間での擦り合わせや協力が重要となります。必ずしもアジャイル開発の経験が豊富である必要はありませんが、ここまで紹介してきたようなアジャイル開発の特徴を理解し、オープンな姿勢でチームや関係者とコミュニケーションを取れる人材が求められます。\n\n「プロダクトオーナー」や開発チームを支援する「スクラムマスター」の役割も重要です。場合によってはアジャイルコーチによるトレーニングを活用したり、経験豊富な外部の専門家にサポートを依頼したりすることも有効です。\n\n### メンバー間で密にコミュニケーションをとる\n\nアジャイル開発を成功に導くためには、顧客を含めた関係者全員がコミュニケーションを密にとっていくことが大切です。先ほど説明したような「デイリースクラム」や「スプリントレビュー」などのミーティングを定期的に実施し、メンバー間でのコミュニケーションを活性化させましょう。\n\nチームメンバーが自由に意見を出しやすい雰囲気の中で開発を進めることで、進捗管理や品質の維持もしやすくなります。特に上下関係などの関係性を取り払って、お互いが率直に提案や指摘をし合えるような環境ならプロジェクトの成功率をより高められるでしょう。\n\n### CI/CDなど自動化のテクノロジーを取り入れる\n\nアジャイル開発をスムーズに進めるためには、[CI/CD](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)など自動化のテクノロジーを取り入れることもポイントです。[CI/CD](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)とは、顧客にプロダクトを素早く提供するために、ビルド作業やテスト、リリースの工程といった、開発フローの一部を自動化する手法のことです。\n\nアジャイル開発と[CI/CD](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)の相性は良く、機能単位ごとの開発フローを[CI/CD](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)によって自動化することによって、一定の品質を維持したままリリース頻度の向上を実現できます。[CI/CD](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)については以下の記事で解説しているので、併せてチェックしてみてください。\n\n[CI/CDとは？意味や導入のメリット・デメリット、ツールの選び方を解説](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)\n\n### 情報の透明性を保つ\n\nアジャイル開発においてはチームメンバーと顧客との間で信頼関係を構築することが求められます。顧客側が開発の中でどのようなことが行われているのかが把握できないと不安を抱いてしまいます。例えば、成果物が納品されるまで状況を掴めないような進め方だと、認識の齟齬が生まれる原因になるでしょう。\n\nそのため、アジャイル開発で扱う情報においては常に透明性をもたせることが大事です。\n\n例えば、以下のような情報に透明性をもたせて、顧客とチームメンバーとの間でスムーズに情報共有できるような仕組みを構築しておきましょう。\n\n* 全体の開発スケジュール  \n* 開発の作業内容  \n* 開発メンバーの保有スキル  \n* 開発の進捗状況 など\n\n情報の透明性を保ち、チームの誰でも同じ情報にアクセスできる状態のことをSingle Source Of Truth（SSOT、信頼できる唯一の情報源）と呼び、これがあることでチームの自律的な行動を促すことができます。こちらに関する記事は下記が詳しいため、併せてチェックしてみてください。\n\n[組織の自律自走を促すコミュニケーション](https://learn.gitlab.com/c/effective-communication-for-autonomous-organization-deck?x=JBqxmQ)\n\n## アジャイル開発におけるセキュリティの課題\n\nアジャイル開発では、仕様変更や機能追加などに対して柔軟に対応でき、スピード感を持って開発を進められます。その一方で、セキュリティが後回しにされたり、おろそかにしてしまったりするケースも多いといわれています。この課題に対応するには、リリース直前に実施される人手による脆弱性診断やペネトレーションテストだけでなく、静的解析ツールやコンテナスキャンなどの自動化されたセキュリティテストを[CI/CD](https://about.gitlab.com/ja-jp/blog/what-is-ci-cd/)パイプラインに組み込むことが効果的です。\n\nなお、セキュリティ対策の重要性はアジャイル開発に限ったことではありません。[IPAの調査](https://www.ipa.go.jp/security/10threats/10threats2024.html)から近年組織ではさまざまなセキュリティインシデントが発生していることがわかります。開発の早い段階でセキュリティ上の問題を発見し、迅速な対応が可能になるこれらのプラクティスは「シフトレフト」と呼ばれ、セキュリティリスクをより早い段階で見つけ、手戻りを少なく品質をあげていく手法として、アジャイル開発以外での開発手法でも重要であると言われています。\n\n## アジャイル開発におけるAI活用について\n![アジャイル開発1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687637/Blog/Content%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA1.jpg)\n\nアジャイル開発を採用する際には、AIを積極的に活用する視点も持っておきましょう。\n\n例えば、前述の通り、アジャイル開発ではリリース直前での脆弱性診断だけでなく、開発段階などでも常時セキュリティスキャンなどで脆弱性を検出することが重要です。この時に[GitLab Duo](https://about.gitlab.com/ja-jp/gitlab-duo/)のようなAIを活用することによってソフトウェアの脆弱性をより効率的に把握して修正でき、開発におけるセキュリティリスクを軽減することができます。\n\nその他にも、テストコードを書いたり、ソースコードからドキュメントから詳細設計書やパラメータシート相当のものを作成するなど、特にアジャイル開発でよく行われることにAIの支援を受けることができ、開発効率の向上を実現することができます。\n\nこれらの機能のデモもありますので、参考にしていただければと思います。\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/jygdsxzBC4Y?si=k6NWiV2Jc29fS0Uu\" title=\"YouTube video player\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen>\u003C/iframe>\n\n## アジャイル開発とDevSecOpsの関係性\n\n先ほど挙げたアジャイル開発のセキュリティの課題においては「[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)」の必要性が高まっています。\n\n[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)とは、開発（Dev）・セキュリティ（Sec）・運用（Ops）を連携した開発アプローチのことです。[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)では、セキュリティを後回しにすることなく、開発工程（Dev）の段階で対策を行い、ソフトウェアの安全性を高めます。\n\nアジャイル開発と[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)は親和性が高く、両者とも迅速なリリースと継続的な改善を推進する手法や考え方です。つまり、アジャイル開発において[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)のアプローチも取り入れることで、セキュリティレベルを高めながら、迅速なソフトウェア開発を実現できます。補足として、アジャイル開発と同様、ウォーターフォール開発でもDevSecOpsの考え方は積極的に取り入れるべきポイントです。\n\nなお、「[GitLab](https://about.gitlab.com/ja-jp/)」なら[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)のアプローチを踏まえたソフトウェア開発が可能です。アジャイル開発の代表的手法である「スクラム」を1つのプラットフォームで運用することもできるため、ぜひ自社のプロジェクトにお役立て下さい。\n\n## アジャイル開発に関するQ＆A\n![アジャイル開発3](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687637/Blog/Content%20Images/%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E9%96%8B%E7%99%BA3.jpg)\n最後にアジャイル開発に関するQ＆Aを紹介します。\n\n### アジャイル開発の普及率は？\n\n「[DX白書2023](https://www.ipa.go.jp/publish/wp-dx/gmcbt8000000botk-att/000108041.pdf)」によると、アジャイル開発を「全社的に活用している」「事業部で活用している」と回答した企業の割合の合計は22.9%となっています。米国の場合は53.9%となっているため、アジャイル開発の普及率において日米差は大きいことがわかります。\n\n### アジャイル開発が失敗する原因は？\n\nアジャイル開発が失敗してしまう原因はさまざまですが、主に以下が挙げられます。\n\n* アジャイル開発に不向きなプロジェクトで採用している  \n* 顧客とチームメンバーとの間でコミュニケーションが不足している  \n* プロダクトオーナーやスクラムマスターが役割を果たせていない \n\nそもそもアジャイル開発に向いていないようなプロジェクトで採用してしまうと、アジャイル開発の強みを活かせず失敗してしまう可能性が高まります。その他、関係者間でのコミュニケーション不足が発生していたりする場合、開発の方向性が大きくブレたりなどの事態を招く原因となるでしょう。\n\n## アジャイル開発の特徴を十分に理解して自社で導入しよう\n\nアジャイル開発なら、開発途中で発生する急な仕様変更にも柔軟に対応でき、顧客ニーズにマッチした価値を提供することが可能です。\n\nしかし、アジャイル開発に限ったことではないですがセキュリティ対策における課題もあるため、[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)のアプローチも積極的に取り入れていく姿勢も求められます。\n\n[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)プラットフォームを提供する[GitLab](https://about.gitlab.com/ja-jp/)では、世界39か国、5,000人を超えるDevSecOps専門家のインサイトが詰まった完全版レポートを無料で公開しています。ソフトウェア開発におけるAI活用や、[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)に興味がある人はぜひご覧下さい。\n\n> [2024グローバルDevSecOpsレポートはこちら](https://about.gitlab.com/ja-jp/developer-survey/?utm_medium=blog&utm_source=blog&utm_campaign=eg_apac_brand_x_x_ja_gitlabjapanblogseo_what-is-agile-development)  \n\n*監修：佐々木 直晴 [@naosasaki](https://gitlab.com/naosasaki) （GitLab合同会社 ソリューションアーキテクト本部 シニアソリューションアーキテクト）*",[752],"agile",{"slug":754,"featured":93,"template":686},"what-is-agile-development","content:ja-jp:blog:what-is-agile-development.yml","What Is Agile Development","ja-jp/blog/what-is-agile-development.yml","ja-jp/blog/what-is-agile-development",{"_path":760,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":761,"content":767,"config":772,"_id":774,"_type":16,"title":775,"_source":18,"_file":776,"_stem":777,"_extension":21},"/ja-jp/blog/what-is-ci-cd",{"title":762,"description":763,"ogTitle":762,"ogDescription":763,"noIndex":6,"ogImage":764,"ogUrl":765,"ogSiteName":700,"ogType":701,"canonicalUrls":765,"schema":766},"CI/CDとは？意味や導入のメリット・デメリット、ツールの選び方を解説","この記事では、CI/CDの概要や導入するメリット、CI/CDツールの選び方などを詳しく解説します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663328/Blog/Hero%20Images/cicd3.jpg","https://about.gitlab.com/blog/what-is-ci-cd","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CI/CDとは？意味や導入のメリット・デメリット、ツールの選び方を解説\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab Japan Team\"},{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2025-03-03\",\n      }",{"title":762,"description":763,"authors":768,"heroImage":764,"date":769,"body":770,"category":14,"tags":771},[705,706],"2025-03-03","ソフトウェア開発においては、顧客に最大限の価値を提供するためにリリース後も繰り返し改善を行なっていくことが求められます。そのプロセスを効率化するために活用できるのが「CI/CD」です。\n\n実際に開発の効率化のための手段のひとつとしてCI/CDの採用を検討している担当者もいるのではないでしょうか。この記事では、CI/CDの概要や導入するメリット、CI/CDツールの選び方などを詳しく解説します。\n\n## CI/CDとは？\n![cicd1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687600/Blog/Content%20Images/cicd1.jpg)\n\nCI/CDとは、ソフトウェア開発におけるビルドやテスト、デプロイなど、従来であれば手作業で介入する必要があったプロセスを自動化して、素早くプロダクトをリリースする手法のことです。\n\n「Continuous Integration」と「Continuous Delivery」の略称であり、日本語で直訳すると「継続的インテグレーション／継続的デリバリー」となります。\n\n## CIとCDの違い\n\nでは、CIとCDではどのような違いがあるのかそれぞれ意味を解説していきます。\n\n### CI （継続的インテグレーション）\n\nCI （継続的インテグレーション）は、ソフトウェア開発において自動ビルドとテストを繰り返し実行することを示します。\n\n複数の開発者が修正したソースコードを頻繁に統合して、不具合がないか確認するためのプロセスです。このプロセスを繰り返し自動的に実行することで、プログラムのバグを早期に発見・改善でき開発を効率よく進められます。\n\n### CD（継続的デリバリー）\n\nCDとは、「継続的デリバリー」という言葉の通り、CIで検証されたソフトウェアを顧客に対して継続的に公開できる仕組みをつくることです。\n\nCIのプロセスにおいて自動ビルドやテストが実行された後に、ステージング環境やテスト環境などに成果物をデプロイし、さらにセキュリティテストや負荷テストなどを実施します。\n\n最終的な本番環境へのデプロイについては手動で承認する形で行い、ボタンをクリックするだけで反映することができます。\n\n### CD（継続的デプロイメント）\n\nCDには、継続的デリバリーの他にも「継続的デプロイメント」の意味もあります。継続的デプロイメントとは、全てのソースコードの変更が自動的に本番環境に反映される仕組みのことです。\n\n継続的デリバリーと継続的デプロイメントの違いは、手動で本番環境にリリースするか自動で行うかという点です。\n\n## CI/CDパイプラインとは？\n\nCI/CDパイプラインとは、ソースコードの変更からテスト、本番環境へのデプロイまでの一連の流れを自動化したプロセスを指します。つまり、CIとCDの両者を組み合わせた仕組みのことです。\n\nCI/CDパイプラインを構築することで、ソフトウェア開発における各工程の連携がスムーズになり、ビルドやテストの工数削減や迅速なリリースを実現できます。\n\n## CI/CDの導入が必要とされる背景とDevSecOps・アジャイル開発との関係性\n![cicd4](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687600/Blog/Content%20Images/cicd4.jpg)\n\nCI/CDの導入がなぜソフトウェア開発の現場で必要とされているのでしょうか。CI/CDと[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)・アジャイル開発との関係性を踏まえながら解説します。\n\n### CI/CDが必要とされる背景\n\n現代は「Society 5.0時代」と呼ばれており、IT技術の発展と進化に伴い多様なシステムを活用して社会を豊かにするという考え方が重要視されています。ビジネスの場においてもテクノロジーの急激な進化に伴い、多くのサービスが生まれる中で企業間での競争が激化しています。\n\nそうした競争に打ち勝っていくためには、変化に柔軟かつ迅速に対応できる開発環境を構築しなければなりません。CI/CDなら一定の品質を維持したうえで開発プロセスを自動化でき、変化に対応しながら迅速にソフトウェアを顧客に届けることが可能です。\n\nこの品質とスピードの両方の課題を解決できるという強みが、ソフトウェア開発の領域においてCI/CDが注目されている理由だといえます。\n\n### DevSecOps・アジャイル開発との関係性\n\nCI/CDは、[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)やアジャイル開発との相性が良い開発手法であり、これらの手法が主流となってきていることも注目される理由のひとつです。つまり、CI/CDは[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)とアジャイル開発を効果的に実現するための重要な要素として位置付けられています。\n\n例えば、アジャイル開発ではスピード感を持って機能をリリースしていくことが求められます。しかし、リリースを頻繁に繰り返すというプロセスは、毎回テストの実施などにおいて  \n開発者の負担が増大してしまうことを意味します。また、[DevSecOps](https://about.gitlab.com/ja-jp/topics/devsecops/)でいう「セキュリティのシフトレフト」という観点でも、コーディング直後にセキュリティスキャンを実施し、見つかったセキュリティ脆弱性を記憶が鮮明なうちに修正する、という先進的な取り組みにおいても、CI/CDは極めて重要な役割を担います。\n\nCI/CDを導入すれば開発プロセスを自動化できるため、アジャイル開発の強みを活かしながらコスト削減と品質の維持、安全なソフトウェア・サービス開発を実現することが可能です。\n\n## CI/CD導入のメリット\n![cicd2](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687600/Blog/Content%20Images/cicd2.jpg)\n\n既に触れている内容でもありますが、改めてCI/CD導入のメリットについて把握しておきましょう。\n\n* 開発スピードを加速化できる  \n* 生産性と品質の向上が期待できる  \n* バグを早期に発見できる\n\n### 開発スピードを加速化できる\n\nCI/CDを導入することで、ソフトウェア開発からリリースまでの時間を短縮できます。\n\nソースコードを変更した後にはビルドやテスト、デプロイなどさまざまな工程を踏む必要があり、これらを全て手作業で行うとかなりの時間を要します。CI/CDなら手動での作業を自動化できるため、迅速に顧客のソフトウェアを提供することが可能です。\n\n### 生産性と品質の向上が期待できる\n\nCI/CDを導入すればテストからリリースまでの工程を自動化できるため、業務負担の削減につながります。これによって手動で作業していた分の時間をより重要なタスクに割くことが可能になり、生産性向上にも寄与するでしょう。\n\n例えば、プロダクトの品質向上に向けた施策立案や、顧客ニーズや市場の変化を踏まえた仕様変更や機能追加などの重要な業務に注力できるようになります。\n\n### バグを早期に発見できる\n\nCI/CD活用によってテスト工程が自動化されることから、頻繁にテストを実施できるようになります。先ほども触れたようにアジャイル開発の場合は頻繁にテストを繰り返す必要があるため、CI/CDの強みを活かすことでバグを早期に発見できます。\n\n早い段階でバグを発見してその都度修正を実施すれば、機能全体に影響を及ぼすような大きな不具合の発生を未然に防止することも可能です。\n\nまた、スピードを意識するあまりテストの実施が抜けてしまったという重大なミスの防止にもつながるでしょう。\n\n## CI/CD導入における考慮点と成功への鍵\n![cicd6](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687600/Blog/Content%20Images/cicd6.jpg)\n\nCI/CDの導入を成功させるためには事前準備や継続的な改善を実施することが大切です。以下で詳しく解説します。\n\n### CI/CDパイプライン構築による開発基盤の強化を図る\n\nCI/CDを活用するためには、CI/CDパイプラインを構築して開発基盤の強化を図る必要があります。\n\n自動化の基準設定とテストコード作成を丁寧に行うことで、その後正しくCI/CDが機能し、ソフトウェア開発における長期的な品質向上の実現につながります。\n\n### 継続的な実施と改善で価値の最大化を実現する\n\nCI/CDの強みを最大限に活かすためには、アジャイル開発のように頻繁にテストとリリースを実施するような開発手法で活用することが大切です。ウォーターフォール開発の場合は、長期的な計画をベースとして開発が進められるため、CI/CDの使用頻度が少なく十分な効果を発揮できません。\n\nまた、CI/CDについては定期的な改善が必要です。例えば、ソフトウェアの変更によってテスト条件の修正を行う場合は、テストコードも書き直さなければなりません。「[GitLab Duo](https://about.gitlab.com/ja-jp/gitlab-duo/)」なら、CI/CDパイプラインの構築やメンテナンス、エラーの発見・分析を効率化できます。\n\n## CI/CDを導入する際のポイント\n\nCI/CDをスムーズに導入する際には以下のようなポイントを押さえておきましょう。\n\n* 必要なリソースを確保する  \n* メンバーに対する教育を行う\n\n### 必要なリソースを確保する\n\nCI/CDを導入する際には、予算や人材、工数の確保が求められます。自社の現状を把握してCI/CD導入にはどのくらいの予算が必要で、事前準備のためにどれだけの工数を必要とするのかを具体的に落とし込んでおくことが大切です。\n\nなお、CI/CDパイプラインの構築においては、DevOpsエンジニアやSREと呼ばれる人材のアサインが必要です。\n\n### メンバーに対する教育を行う\n\nCI/CDを導入して正しく運用していくためには、チームメンバー全体の理解が必要です。具体的には「自社でCI/CDを導入する目的や解決したい課題」「CI/CD関連でよく使用される用語」「CI/CDツールの使い方・運用ルール」などをメンバーに教育し、理解を深めてもらいます。\n\nしかし、チームメンバーに教育するには時間とコストが多くかかってしまい、その期間は利益を生み出していないことを意味します。「[GitLab Duo](https://about.gitlab.com/ja-jp/gitlab-duo/)」なら、AIによりソフトウェア開発のワークフロー全体を効率化できるため、人材の採用や教育コストの削減にもつなげられます。\n\n## CI/CDツールの選び方\n![cicd5](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749687600/Blog/Content%20Images/cicd5.jpg)\n\nCI/CDツールは以下の５つの観点を意識して選びましょう。\n\n* 機能  \n* 提供形態  \n* コスト  \n* セキュリティ  \n* サポート体制\n\n### 機能\n\nまずは、自社の開発プロジェクトに必要な機能が搭載されているか確認します。例えば、以下のような機能が搭載されたツールを選ぶと良いでしょう。\n\n* CI/CDパイプラインの構築やメンテナンス機能  \n* [API](https://about.gitlab.com/ja-jp/blog/what-is-an-api/)やプラグインなどの連携機能  \n* 優れた拡張機能 など\n\n### 提供形態\n\nCI/CDツールにおいては、クラウド型とオンプレミス型の提供形態があります。\n\nクラウド型はインターネット接続を通して提供元のツールを利用する方法で、サーバーを自社で管理する必要がなく手軽に導入できることがメリットです。ただし、カスタマイズ性は劣ります。\n\n一方、オンプレミス型は自社でサーバーを用意してツールを利用する方法です。オンプレミス型の場合は、カスタマイズ性が高く、インターネット上のセキュリティリスクが軽減できることから、特に機密性の高いデータを扱うビジネスや規制の強い業種にむいています。その反面、サーバー構築に手間がかかりますので、両者の特徴を把握したうえで自社にマッチした利用形態を選択しましょう。\n\n[GitLabでは、クラウド型とオンプレミス型の両方を提供しており、自社の置かれた状況に最適な構築が可能です](https://about.gitlab.com/ja-jp/pricing/)。\n\n### コスト\n\nCI/CDツールを導入する際には当然コストが発生するため、自社の予算と照らし合わせながら利用に必要なコストを確認します。\n\nその際、コストを抑えたいからといって自社に必要な機能が搭載されていないツールを導入しても効果は得られないため、機能面も考慮しながらチェックするのがポイントです。\n\nまた、いきなり開発環境を変えてしまうとリスクもあるため、まずは無料トライアルを受けられるツールを選定して使用感を確かめておきましょう。\n\n### セキュリティ\n\n近年企業においてもさまざまなセキュリティインシデントが発生しています。ソフトウェア開発におけるセキュリティリスクを軽減するためには、CI/CDツールが持つセキュリティスキャン等の機能もチェックしておきましょう。\n\n例えば、AI機能を搭載したツールならソースコードの脆弱性をより効率的に把握して修正できます。また、CI/CDツール製品そのものに、開発元からセキュリティパッチが迅速に提供されているかどうかもチェックしておきたいポイントです。\n\n### サポート体制\n\nCI/CDツールの導入や運用においてトラブルが発生する場合もあります。その際ツール提供側でサポート体制が提供されていると、早期の問題解決につながります。\n\nそのため、サポートプランの有無を確認し、窓口の対応時間や連絡方法をチェックしておきましょう。また、ユーザーコミュニティが活発化しているか、参考資料やドキュメントが充実しているかなども確認しておくと良いでしょう。\n\n## CI/CDツールなら「GitLab」\n\nCI/CDツールをお探しならぜひ「[GitLab](https://about.gitlab.com/ja-jp/)」をご検討下さい。CI/CDの機能を確保する際には、別々のツールを管理してそれらを統合することで実現しているケースがよく見られます。しかし、この構築方法ではツールの選定や準備にも手間がかかり、効率が良いとはいえません。\n\nAIを搭載したGitLabなら、単一の統合ツールとしてCI/CDパイプラインの効率化、セキュリティ対策、品質向上、運用コストの削減などを実現することができます。実際にさまざまな企業でGitLabが導入され、リリースサイクルの短縮に成功しています。\n\nまた、GitLabではクラウド型、オンプレミス型の両方を提供していますので、自社の環境に最適な方をお選びいただけます。60日間の無料トライアル版もご用意しているため、まずは使用感をお試しください。[サポート体制](https://about.gitlab.com/support/)や[参考ドキュメント](https://docs.gitlab.com/)も充実しているため、安心して運用いただけます。\n\n## CI/CDを導入して開発効率の向上を図ろう\n\nソフトウェアの開発においてCI/CDを導入することで、開発スピードや生産性向上などが期待できます。CI/CDを導入して自社のプロジェクトを成功させるためには、適切なCI/CDパイプライン構築と、継続的なメンテナンスを徹底する意識を持つことが大切です。\n\nCI/CDツールの選定においては、ぜひ「[GitLab](https://about.gitlab.com/ja-jp/)」をご検討下さい。GitLabならCI/CDの実現に必要な機能が搭載されているため、スムーズな導入を実現できます。\n\nGitLabによるCI/CDの事例はこちらからご覧下さい。\n\n> [CI/CDと堅牢なセキュリティスキャンがHilti社のSDLCを加速した方法](https://about.gitlab.com/ja-jp/customers/hilti/?utm_medium=blog&utm_source=blog&utm_campaign=eg_apac_brand_x_x_ja_gitlabjapanblogseo)\n\n\u003Cbr>\u003Cbr>\u003Cbr>\n\n*監修： ハシュカ アンドリュー /Andrew Haschka [@tkomatsubara](https://gitlab.com/tkomatsubara)\u003Cbr>\n（GitLab合同会社 ソリューションアーキテクト本部 シニアパートナーソリューションアーキテクト）*",[111],{"slug":773,"featured":93,"template":686},"what-is-ci-cd","content:ja-jp:blog:what-is-ci-cd.yml","What Is Ci Cd","ja-jp/blog/what-is-ci-cd.yml","ja-jp/blog/what-is-ci-cd",{"_path":779,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":780,"content":786,"config":796,"_id":798,"_type":16,"title":799,"_source":18,"_file":800,"_stem":801,"_extension":21},"/ja-jp/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab",{"title":781,"description":782,"ogTitle":781,"ogDescription":782,"noIndex":6,"ogImage":783,"ogUrl":784,"ogSiteName":700,"ogType":701,"canonicalUrls":784,"schema":785},"Amazon ECRからGitLabへのコンテナイメージ移行の自動化","プラットフォームチームがCI/CDをGitLabに移行する際、コンテナイメージの移行がボトルネックになってはなりません。このガイドでは、パイプライン移行を自動化する方法を詳しく解説します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663129/Blog/Hero%20Images/blog-image-template-1800x945__28_.png","https://about.gitlab.com/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Amazon ECRからGitLabへのコンテナイメージ移行の自動化\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tim Rizzi\"}],\n        \"datePublished\": \"2025-02-13\",\n      }",{"title":781,"description":782,"authors":787,"heroImage":783,"date":789,"body":790,"category":14,"tags":791},[788],"Tim Rizzi","2025-02-13","「Amazon Elastic Container Registry（ECR）からGitLabに数百ものコンテナイメージを移行する必要があるのですが、手伝ってもらえますか？」これまでのプラットフォームエンジニアとの会話の中で、何度もこの質問が出てきました。彼らは、DevSecOpsツールチェーンをGitLabに統合してモダナイズしようとしていたものの、コンテナイメージの移行の箇所でつまずいていました。個々のイメージの移行は簡単でも、数が多すぎると、手作業で行うのは現実的ではありません。\n\nまさに、あるエンジニアは「やるべきことはわかっています。プルして、再タグ付けして、プッシュするだけです。しかし、マイクロサービスが200個もあり、それぞれに複数のタグがあります。インフラストラクチャ関連の重要な仕事が山積みの中、この移行作業に何週間も費やすわけにはいきません」と話していました。\n\n## 課題\n\nこの会話をきっかけに、プロセス全体を自動化できないかと考えました。[CI/CD](https://about.gitlab.com/ja-jp/topics/ci-cd/)をGitLabに移行する際、コンテナイメージの移行がボトルネックになってはなりません。手作業はシンプルですが、繰り返しが多すぎます。各イメージをプルし、再タグ付けし、GitLabのコンテナレジストリにプッシュする…これを数十のリポジトリ、各イメージの何百ものタグに対して行うとなると、数日から数週間かかる途方もない作業になります。\n\n## 解決策\n\nそこで、こういった大変な作業を自動処理するGitLabパイプラインの作成に取り掛かりました。目標はシンプルです。プラットフォームエンジニアが数分でセットアップできて、一晩放置すればすべてのイメージの移行が完了している、そんなツールを作ることでした。\n\n### アクセス権の設定\n\nまずはセキュリティです。チームが最小限のAWS権限でこの移行作業を実行できるようにすることを重視しました。以下の読み取り専用のアイデンティティおよびアクセス管理（IAM）ポリシーを用意しました。\n\n```json\n{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"ecr:GetAuthorizationToken\",\n                \"ecr:BatchCheckLayerAvailability\",\n                \"ecr:GetDownloadUrlForLayer\",\n                \"ecr:DescribeRepositories\",\n                \"ecr:ListImages\",\n                \"ecr:DescribeImages\",\n                \"ecr:BatchGetImage\"\n            ],\n            \"Resource\": \"*\"\n        }\n    ]\n}\n```\n\n### GitLabの設定\n\nセキュリティの次はGitLab側の設定です。最小限の構成で済むようにしました。CI/CD設定で以下の変数を設定します。\n\n```\nAWS_ACCOUNT_ID: AWSのアカウントID\nAWS_DEFAULT_REGION: ECRのリージョン\nAWS_ACCESS_KEY_ID: [マスク]\nAWS_SECRET_ACCESS_KEY: [マスク]\nBULK_MIGRATE: true\n```\n\n### 移行パイプライン\n\nここからが本番です。このパイプラインはDocker-in-Dockerを使って構築し、すべてのイメージ操作を安定して実行できるようにしました。\n\n```yaml\nimage: docker:20.10\nservices:\n  - docker:20.10-dind\n\nbefore_script:\n  - apk add --no-cache aws-cli jq\n  - aws sts get-caller-identity\n  - aws ecr get-login-password | docker login --username AWS --password-stdin\n  - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}\n```\n\nこのパイプラインは3つのフェーズで構成され、それぞれが前のフェーズをベースにします。\n\n1. 検出\n\nまず、すべてのECRリポジトリを取得します。\n\n```bash\nREPOS=$(aws ecr describe-repositories --query 'repositories[*].repositoryName' --output text)\n```\n\n2. タグの列挙\n\n次に、各リポジトリの全タグを取得します。\n\n```bash\nTAGS=$(aws ecr describe-images --repository-name $repo --query 'imageDetails[*].imageTags[]' --output text)\n```\n\n3. 移行\n\n最後に、実際にイメージ移行を実行します。\n\n```bash\ndocker pull ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag}\ndocker tag ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${repo}:${tag} ${CI_REGISTRY_IMAGE}/${repo}:${tag}\ndocker push ${CI_REGISTRY_IMAGE}/${repo}:${tag}\n```\n\n## 期待できる成果\n\n移行に何週間もかける時間がないというプラットフォームエンジニアのために、このソリューションは次のような成果を提供します。\n\n- すべてのリポジトリとタグを自動的に検出・移行\n- ECRとGitLabのイメージ命名規則を統一\n- 転送失敗時のエラーハンドリング\n- 進捗を追跡できる明確なログ\n\n\n移行スクリプトを書いたり、移行作業を監視したりする必要がなくなり、プラットフォームエンジニアは他の重要な作業に集中できるようになります。\n\n## 使い方\n\n手順はシンプルです。\n\n1. `.gitlab-ci.yml`をリポジトリにコピー\n2. AWSとGitLabの変数を設定\n3. `BULK_MIGRATE`を「true」に設定して、移行を開始\n\n## ベストプラクティス\n\nさまざまなチームの移行を支援する中で、いくつかの重要なポイントが見えてきました。\n\n- ピーク時以外に実行し、チームへの影響を最小限に抑える\n- パイプラインのログを確認し、必要な対応がないかチェックする\n- すべてのイメージが正常に転送されたことを確認するまで、ECRを廃止しない\n- 大規模な移行の場合、ネットワーク負荷を避けるためにレート制限の適用を検討する\n\nこのパイプラインは、GitLabの公開リポジトリでオープンソースとして提供しています。プラットフォームエンジニアがコンテナイメージの移行に時間を取られるのではなく、本来の業務に専念できるよう設計されています。ニーズに応じてカスタマイズしてお使いください。実装についてのご質問もお待ちしています。\n\n> #### このパッケージおよびその他のコンポーネントの詳細については、[CI/CDカタログのドキュメント](https://gitlab.com/explore/catalog/components/package)をご覧ください。",[111,792,684,793,794,795],"AWS","DevSecOps platform","product","solutions architecture",{"slug":797,"featured":93,"template":686},"automating-container-image-migration-from-amazon-ecr-to-gitlab","content:ja-jp:blog:automating-container-image-migration-from-amazon-ecr-to-gitlab.yml","Automating Container Image Migration From Amazon Ecr To Gitlab","ja-jp/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab.yml","ja-jp/blog/automating-container-image-migration-from-amazon-ecr-to-gitlab",{"_path":803,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":804,"content":810,"config":815,"_id":817,"_type":16,"title":818,"_source":18,"_file":819,"_stem":820,"_extension":21},"/ja-jp/blog/what-is-an-api",{"title":805,"description":806,"ogTitle":805,"ogDescription":806,"noIndex":6,"ogImage":807,"ogUrl":808,"ogSiteName":700,"ogType":701,"canonicalUrls":808,"schema":809},"APIとは？意味から注目のAPIゲートウェイまで徹底解説","APIとは？API gateway、API連携などについて基本的な意味やメリットなどAPIについて知っておきたいことをすべて解説します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665215/Blog/Hero%20Images/API.jpg","https://about.gitlab.com/blog/what-is-an-api","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"APIとは？意味から注目のAPIゲートウェイまで徹底解説\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"GitLab\"}],\n        \"datePublished\": \"2024-12-16\",\n      }",{"title":805,"description":806,"authors":811,"heroImage":807,"date":812,"body":813,"category":14,"tags":814},[706],"2024-12-16","1. APIとは？  \n2. API連携のしくみ  \n3. API利用のメリット  \n4. APIを利用する際の注意点  \n5. APIの種類  \n6. API連携が使われている事例  \n7. 注目のAPI提供元とそのサービス  \n8. APIゲートウェイとは？  \n9. API連携・APIゲートウェイのよくある質問\n\nAPIは、あるソフトウェアの機能をほかのソフトウェアから呼び出す仕組みのことです。「Application Programming Interface（アプリケーションプログラミングインターフェース」）の略称で、SNSやECサイト、POSレジなど多様な業界に点在しています。\n\nこの記事では、APIを理解するために、その仕組みから活用事例、注目のAPIゲートウェイまで解説していきます。\n\n## APIとは？   \nAPI連携は、その名の通り、APIを利用してアプリケーションの機能やデータを他のアプリケーションやシステムと連携させ、利用できる機能を拡張することです。事前登録したクレジットカードから自動決済されるシステムやカレンダー機能を使った自動予約システムなどにもAPIが使われています。API連携によって、プログラムをゼロから開発しなくても既存のソフトウェアやウェブサービスが提供している機能を活用できるため、効率よく顧客体験を向上させることができるため、幅広い業界で活用が広がっています。\n\n## API連携のしくみ   \nAPI連携はリクエスト（要求）とレスポンス（応答）で成り立っています。利用者側がリクエストし、提供元がレスポンスするという構図です。API連携のためには、APIの提供元は事前にどのようなリクエストに対してどのようなレスポンスを返すのかルールを設定しなければなりません。利用者はそのルールに則ったコードを書くことでAPIを連携させることができます。\n\n## API利用のメリット    \nAPIを使うメリットは大きく３つあります。\n\n### サービスの拡張\nAPIを利用することで、本来は扱うことのできなかったデータ交換や処理ができるようになります。従来のようにすべての機能を社内で開発した場合、新機能やサービスの開発に多くの時間やコストがかかりました。しかし、API連携を使うことでプログラムの設計や開発、より少ない工数で高度な機能を実装できます。 顧客満足度を高めるサービスが低コストで導入できるようになるのです。\n\n### 開発コストの削減 \n無料で提供されているAPIも多くありますし、有償APIも自社で開発から構築まで取り組んだ場合にかかる費用と比べれば、低コストに抑えられることがほとんどです。\n\n### セキュリティを向上させるには\n自社開発でセキュリティを向上させるには、モバイルデバイスを利用した二段階認証などといった認証システムを構築する必要がありますが、API連携の認証サービスを使えば、実績のあるクラウドサービスの認証システムを手軽に利用することが可能です。\n\n## APIを利用する際の注意点  \n一方で、API提供元の問題が、自社サービスの問題に直結することに注意が必要です。提供元企業がサービスの提供を中止した場合には、自社サービスの提供もできなくなる可能性があります。API提供元のサーバーに不具合や障害が発生し、サービスが使えなくなることも想定しなければなりません。トラブルを事前に想定し、リスクに備えておくことが大切です。\n\n## APIの種類 \nAPIには提供される目的や用途に応じていくつかの種類があり、いずれも提供元や活用方法が異なります。どのAPIを使うのが最適か判断するためにも、APIの種類について理解しておきましょう。\n\n### Web API\nWebを介して機能の一部が提供されるAPIです。「HTTP/HTTPS」の通信方式を使ってインターネット経由でリクエスト／レスポンスのやり取りが行われます。プログラミング言語や使用するパソコンのOSに関係なく、あらゆる環境からアクセスが可能な点が大きな強みであり、多くの企業からさまざまなAPIが提供されています。\n\n### ネイティブAPI\nWindowsやAndroidのようなOSが提供する「ネイティブAPI」。OSが持っている機能を、他のアプリケーションでも呼び出すことができるAPIです。WindowsがOSとして持っている機能をサードパーティ製のアプリでも使えるようにしています。OSが進化するとともに、OSが提供する機能は多岐にわたり、手軽にAPIを使えるようなツール（フレームワーク）が提供されることも増えています。\n\n### その他のAPI  \n他にもJavaやC++のようなプログラミング言語が提供する「ライブラリAPI」や「ランタイムAPI」があり、プログラミング言語が持つ能力を最大限発揮できるような環境を整えています。また、データベースが提供する「データベースAPI」では、データベース内部のデータを効率的に扱えるようなAPIを提供しています。\n\n## API連携使用例   \n具体的にどのような場面でAPI連携が使われているのでしょうか。\n\n- SNS  \n- ECサイト  \n- POSレジ\n\n以上３つの例を具体的に説明します。\n\n### SNS  \n近年、SNSは企業と個人を繋ぐツールとして不可欠な存在となりつつあります。世界中に顧客を持つ企業では、よりきめ細かなカスタマーケアを提供する方法としてX（旧Twitter）で公開されているAPI「Sprout Social」はDM（ダイレクトメール）やメンション、リプライなどで言及されたユーザーからの要望や質問を、企業内の担当者に直接転送してくれます。また、カスタマーフィードバック機能では、XのDMで製品やサービスの満足度に関するアンケート調査を行えます。質問への回答率の向上や解答までの時間短縮が顧客体験の向上を実現します。ほかにもLINEを使った荷物の再配達設定など、SNSを使った顧客体験の向上は広い業界に広がっています。\n\n### ECサイト  \n決済サービスの運営事業者はECサイト向けのAPIやサードパーティアプリを提供しています。例えば、楽天ペイでは決済処理APIを提供しており、API連携をしたECサイトで楽天会員が決済する場合、楽天ペイに登録済みの情報を呼び出して決済することができます。個人情報を入力して会員登録をする手間を省けるため、顧客体験やコンバージョン率の向上が見込めます。\n\n### POSレジ \n販売情報を集計・記録するPOSレジでもAPI連携が広がっています。顧客管理システムとの連携で会員情報の共有や購買履歴にあわせた商品レコメンドが可能になります。また、在庫管理システムとの連携で仕入れ効率を向上するなどデータ管理の効率化でも使われています。業種や店舗形態によって様々な活用が広がっています。\n\n## 注目のAPI提供元とそのサービス  \nここからは、注目のAPI提供元をご紹介します。\n\n### Google \nGoogleでは、クラウド基盤である「Google Cloud Platform」上で、利用できるAPIをライブラリにまとめており、GmailやMap、YouTube、Calendar、Driveの他、300種類のAPIが公開されています。こうしたAPIを使って、メールを簡単に取得するツールやカレンダーアプリを作ったり、ブラウザの拡張機能や画像認識を使ったスマホアプリ、ソフトウェア、Webサービスを構築できます。\n\n### X（旧Twitter） \n大手SNSであるXもAPIを提供しています。Webサイトに表示される投稿内容や投稿をまとめたり、自動で投稿してくれるツールなど、すべてAPIをベースに作られています。SNSを使った情報発信や、情報収集を効率化したい場合には、真っ先にチェックすべきAPIと言えるでしょう。\n\n### OpenAI  \n話題のChatGPTを提供するOpenAIもAPIを提供しています。画像生成、機会文字起こし、自動分類、機械学習を実装するAPIに注目が集まっています。\n\n### ヤマト運輸 \nWebAPIにより、配送連携APIを提供しています。二次元コードをかざすだけでコンビニやオープン型宅配便ロッカーからの荷物発送するため、匿名配送や発送時の支払い簡略化が可能になり、高い顧客満足を誇っています。\n\n### Slack\nアメリカ発のビジネス向けコミュニケーションツールであるSlackも、「Slack API」という独自のAPIを提供しています。利用することで、リマインドやリアルタイムでのアラートなどの通知が行えます。Botを活用し、タスク自動化、メッセージの送受信や会話へのリアクションなども実装できます。  \n\nSlackへ外部サービスからのAPIも提供されており、例えば[GitLabもSlack向けのAPI](https://about.gitlab.com/ja-jp/solutions/slack/)を提供しています。\n\n## API ゲートウェイとは？  \nAPIゲートウェイは、APIの管理ツールです。うまく設計、管理されているAPIなら、迅速にビジネスの新しい製品とサービスを繋ぎ合わせ、顧客体験の向上やセキュリティの強化が期待できます。しかし、API連携は実装・管理ともに容易ではありません。この問題を解決してくれるのがAPIゲートウェイです。  \n\nAPIゲートウェイはクライアントとバックエンドサービスのコレクションの間に位置し、リクエストを効率的に処理することで、クライアントとアプリ間のやりとり回数を削減し、顧客体験を向上させます。たとえば、複数のAPIと連携を行う場合、通常それぞれ個別にデータの送受信をする必要がある場合にAPIゲートウェイが、データを使う側からのリクエストをそれぞれのAPIへ振り分け、集約し適正なレスポンスを返却してくれます。複数のAPIを管理できるAPIゲートウェイの機能には、認証、監視、アラートなどさまざまな種類があります。  \n\n開発したAPIに含まれるセキュリティの脆弱性を効率的に検知・修正できるような[セキュリティテスト機能を持つAPIゲートウェイ](https://about.gitlab.com/ja-jp/solutions/security-compliance/)の導入がおすすめです。\n\n## API連携・APIゲートウェイのよくある質問 \n\n### APIとは何ですか？\n\nAPIとは、「Application Programming Interface（アプリケーションプログラミングインターフェース」）の略称です。自社の持つサービスの一部を外部でも使えるように公開する手段です。API連携によって、プログラムをゼロから開発しなくても既存のソフトウェアやウェブサービスが提供している機能を活用できるため、効率よく顧客体験を向上させることができるため、幅広い業界で活用が広がっています。\n\n### APIゲートウェイとは何ですか？\n\nAPIゲートウェイとは、APIの管理ツールです。複数のAPIと連携を行う場合、APIゲートウェイを使えば、APIゲートウェイがそれぞれのAPIへリクエストを振り分け、集約し適正なレスポンスを返却してくれます。\n\n### APIを使うメリットは？\n\nAPIを使えば、外部サービスの機能やデータを自社サービスで使用できます。低コスト、低負荷で機能拡張や新規ビジネス参入ができると近年注目を集めています。\n\n### APIはどんな種類がありますか？\n\n代表的なものには、インターネットを介して提供される「WebAPI」、WindowsなどのOSにより提供される「ネイティブAPI」などがあります。\n\n### APIは誰でも利用できますか？\n\n基本的には誰でも利用可能です。ただし、利用における必要な技術や、APIによっては有償化されているものもあるので、利用する際には、きちんとした理解と検討が必要です。  \n\nいかがでしたでしょうか？ APIやAPI連携、APIゲートウェイについて正しく理解し、有益な連携を始めましょう。  \nGitLabでも多彩なAPIを提供しています。[GitLab](https://about.gitlab.com/ja-jp/)の利便性の高いAPIを、ぜひこの機会に体験してください。  \n\n[GitLabについて詳しく知る](https://about.gitlab.com/ja-jp/devsecops/)\n",[711,236],{"slug":816,"featured":93,"template":686},"what-is-an-api","content:ja-jp:blog:what-is-an-api.yml","What Is An Api","ja-jp/blog/what-is-an-api.yml","ja-jp/blog/what-is-an-api",{"_path":822,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":823,"content":829,"config":838,"_id":840,"_type":16,"title":841,"_source":18,"_file":842,"_stem":843,"_extension":21},"/ja-jp/blog/using-child-pipelines-to-continuously-deploy-to-five-environments",{"title":824,"description":825,"ogTitle":824,"ogDescription":825,"noIndex":6,"ogImage":826,"ogUrl":827,"ogSiteName":700,"ogType":701,"canonicalUrls":827,"schema":828},"子パイプラインを使用して5つの環境に継続的にデプロイする","使用するGitLabワークフローを最小限に抑えつつ、複数の環境（事前の準備なしに一時的に利用できるsandboxなど）への継続的デプロイを管理する方法を解説します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097012/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_397632156_3Ldy1urjMStQCl4qnOBvE0_1750097011626.jpg","https://about.gitlab.com/blog/using-child-pipelines-to-continuously-deploy-to-five-environments","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"子パイプラインを使用して5つの環境に継続的にデプロイする\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Olivier Dupré\"}],\n        \"datePublished\": \"2024-09-26\",\n      }",{"title":824,"description":825,"authors":830,"heroImage":826,"date":832,"body":833,"category":14,"tags":834,"updatedDate":837},[831],"Olivier Dupré","2024-09-26","DevSecOpsチームでは、複数の環境にまたがる継続的デプロイを管理する機能が必要となることがあります。その場合、ワークフローを変更せずに、デプロイを行えるようにする必要があります。[GitLab DevSecOpsプラットフォーム](https://about.gitlab.com/)なら、事前の準備なしに一時的に利用できるsandboxを使用して工数を最小限に抑えるアプローチなどを通じて、こうしたニーズに対応できます。この記事では、Terraformを使って複数の環境上でインフラの継続的デプロイを行う方法についてご紹介します。\n\nこの手法は、[Pulumi](https://www.pulumi.com/)や[Ansible](https://www.ansible.com/)のような別の技術を使用したInfrastructure as Code（IaC）でも、どのような言語で書かれたソースコードでも、または多様な言語が混在するモノレポであっても、あらゆるプロジェクトに簡単に適用できます。\n\nこのチュートリアルの終了時には、以下のような環境をデプロイするパイプラインが完成します。\n\n* 各フィーチャーブランチの一時的な**レビュー（review）**環境。\n* 簡単に消去可能で、mainブランチからデプロイされる**統合（integration）**環境。\n* **品質管理（qa）**環境。同様にmainブランチからデプロイされ、品質管理プロセスを実行します。\n* タグ付けされるたびにデプロイされる**ステージング（staging）**環境。これは本番環境前の最後のステージです。\n* ステージング環境の直後の**本番（production）**環境。今回はデモ用に手動でトリガーしますが、継続的にデプロイされるようにすることも可能です。\n\n>この記事で使用されるフローチャートの説明は以下のとおりです。\n> * 角が丸いボックスはGitLabブランチです。\n> * 四角のボックスは環境です。\n> * 矢印上のテキストは、あるボックスから次のボックスへのアクションを指します。\n> * ひし形のボックスは決定ステップです。\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    A(main) -->|新機能| B(feature_X)\n\n    B -->|自動デプロイ| C[review/feature_X]\n    B -->|マージ| D(main)\n    C -->|破棄| D\n\n    D -->|自動デプロイ| E[integration]\n    E -->|手動| F[qa]\n\n    D -->|タグ付け| G(X.Y.Z)\n    F -->|検証| G\n\n    G -->|自動デプロイ| H[staging]\n    H -->|手動| I{plan}\n    I -->|手動| J[production]\n\u003C/pre>\n\nステップごとに、[理由](#why)と[行うこと](#what)を説明した上で、[方法](#how)をご紹介します。これにより、このチュートリアルを完全に理解し、正確に実行しやすくなります。\n\n## 理由\n\n* [継続的インテグレーション](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-integration-ci)はほぼ事実上の業界標準と言えます。ほとんどの企業は、CIパイプラインを実装済みであるか、その実践の標準化を検討しています。\n\n* また、CIパイプラインの最後にリポジトリまたはレジストリにアーティファクトをプッシュする[継続的なデリバリー](https://about.gitlab.com/topics/ci-cd/#what-is-continuous-delivery-cd)も一般的です。\n\n* 継続的デプロイメントはさらに進んで、これらのアーティファクトを自動的にデプロイしますが、その普及はまだ限定的です。導入されている場合、主にアプリケーション分野で見られます。インフラの継続的デプロイメントに関しては、状況がやや不明瞭で、複数の環境の管理に重きが置かれる傾向があります。一方で、インフラのコードをテストし、セキュリティを確保し、検証することはより難しいとされています。この分野は、DevOpsがまだ成熟に至っていない分野のひとつです。ほかの分野としては、セキュリティのシフトレフトが挙げられます。具体的には、セキュリティチームの介入、さらに重要なことに、セキュリティ上のリスクへの対応をデリバリーライフサイクルの早期に組み込み、DevOpsから***DevSecOps***へと発展させる取り組みのことです。\n\nこのような概況を踏まえ、本チュートリアルでは、インフラにDevSecOpsをシンプルかつ効果的に導入するシナリオに取り組みます。5つの環境にリソースをデプロイする例を交えながら、開発から本番環境へと段階的に進めていきます。\n\n__注__：個人的にはFinOpsアプローチを採用し、環境の数を減らすことを推奨していますが、開発環境、ステージング環境、本番環境以外の環境を保持すべき場合もあります。そのため、これからご紹介する例をご自身のニーズに合わせて調整してください。\n\n## 行うこと\n\nクラウド技術の台頭により、IaCの利用が促進されています。この分野を最初に開拓したのは、AnsibleとTerraformでした。OpenTofu、Pulumi、AWS CDK、Google Deploy Managerを始めとする多くの会社がその後に続きました。\n\nIaCを定義することは、インフラストラクチャを安全にデプロイするのに最適なソリューションです。目標を達成できるまで必要なだけ、テスト、デプロイ、再実行を繰り返し行えます。\n\n残念なことに、ターゲット環境ごとに複数のブランチやリポジトリを保持している企業がよくあります。これが原因で問題が生じます。こういった企業では、プロセスの実施が徹底されていません。本番環境のコードベースへの変更が、その前の環境で正しくテストされているかどうかも確認できません。その結果、ある環境から別の環境へ流れるだけになります。\n\nこのチュートリアルが必要だと気づいたのは、あるカンファレンスに参加した際に、本番環境へのデプロイ前にインフラストラクチャを十分にテストするワークフローがないと参加者全員から聞いたときです。みなが、本番環境で直接コードにパッチを適用することもあると言っていました。確かにこの方法は手っ取り早いですが、果たして安全でしょうか？前の環境にフィードバックをどう戻すのでしょうか？また副次効果が生じないようにするにはどうすればよいのでしょうか？新たな脆弱性が本番環境にあまりにも早くプッシュされることで会社がリスクにさらされないようにするには、どのように管理すべきでしょうか？\n\nここで重要なのは、DevOpsチームが本番環境に直接デプロイするのは*なぜ*かということです。パイプラインの効率性や速度を向上できる可能性があるためでしょうか？自動化できないのでしょうか？それどころか、*本番環境以外で正確にテストする方法がない*からなのでしょうか？\n\n次のセクションでは、インフラストラクチャを自動化し、ほかの人に影響を及ぼす環境にコードがプッシュされる前に、DevOpsチームが効果的かつ確実にテストを実施するための方法をご説明します。また、コードがどのように保護され、エンドツーエンドでデプロイが管理されているかも確認していきます。\n\n## 方法\n\n前述のとおり、現在では多くのIaC言語が存在しているため、この記事だけで客観的に*すべて*を取り上げることはできません。そのため、この記事ではバージョン1.4で実行される基本的なTerraformコードを使用します。IaC言語そのものではなく、貴社のエコシステムに適用できるプロセスに注目してください。\n\n### Terraformコード\n\nまずは、基本的なTerraformコードから始めましょう。\n\n仮想ネットワークであるAWSの仮想プライベートクラウド（VPC）にデプロイしたいと思います。VPCには、パブリックサブネットとプライベートサブネットをデプロイします。名前からわかるように、これらはメインVPCのサブネットです。最後に、パブリックサブネットにAmazon Elastic Cloud Compute（EC2）インスタンス（仮想マシン）を追加します。\n\nこれは、比較的簡単な方法で4つのリソースをデプロイする方法を示しています。コードではなく、パイプラインに焦点を当てることがここでの目的です。\n\nここで目指すリポジトリの完成形は、以下のとおりです。\n\n![リポジトリの完成図](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750097033415.png)\n\nステップごとに行っていきましょう。\n\nまずは、`terraform/main.tf`ファイルでリソースをすべて宣言します。\n\n```terraform\nprovider \"aws\" {\n  region = var.aws_default_region\n}\n\nresource \"aws_vpc\" \"main\" {\n  cidr_block = var.aws_vpc_cidr\n\n  tags = {\n    Name     = var.aws_resources_name\n  }\n}\n\nresource \"aws_subnet\" \"public_subnet\" {\n  vpc_id     = aws_vpc.main.id\n  cidr_block = var.aws_public_subnet_cidr\n\n  tags = {\n    Name = \"Public Subnet\"\n  }\n}\nresource \"aws_subnet\" \"private_subnet\" {\n  vpc_id     = aws_vpc.main.id\n  cidr_block = var.aws_private_subnet_cidr\n\n  tags = {\n    Name = \"Private Subnet\"\n  }\n}\n\nresource \"aws_instance\" \"sandbox\" {\n  ami           = var.aws_ami_id\n  instance_type = var.aws_instance_type\n\n  subnet_id = aws_subnet.public_subnet.id\n\n  tags = {\n    Name     = var.aws_resources_name\n  }\n}\n```\n\nご覧のとおり、このコードではいくつかの変数が必要となるため、`terraform/variables.tf`ファイルでそれらを宣言します。\n\n```terraform\nvariable \"aws_ami_id\" {\n  description = \"The AMI ID of the image being deployed.\"\n  type        = string\n}\n\nvariable \"aws_instance_type\" {\n  description = \"The instance type of the VM being deployed.\"\n  type        = string\n  default     = \"t2.micro\"\n}\n\nvariable \"aws_vpc_cidr\" {\n  description = \"The CIDR of the VPC.\"\n  type        = string\n  default     = \"10.0.0.0/16\"\n}\n\nvariable \"aws_public_subnet_cidr\" {\n  description = \"The CIDR of the public subnet.\"\n  type        = string\n  default     = \"10.0.1.0/24\"\n}\n\nvariable \"aws_private_subnet_cidr\" {\n  description = \"The CIDR of the private subnet.\"\n  type        = string\n  default     = \"10.0.2.0/24\"\n}\n\nvariable \"aws_default_region\" {\n  description = \"Default region where resources are deployed.\"\n  type        = string\n  default     = \"eu-west-3\"\n}\n\nvariable \"aws_resources_name\" {\n  description = \"Default name for the resources.\"\n  type        = string\n  default     = \"demo\"\n}\n```\n\nすでにIaC側に関しては、これでほぼ準備が整いました。しかしながら、これではTerraformの状態を共有できません。ご存知ない方のために大まかに説明すると、Terraformは以下を行うことで動作します。\n\n* `plan`により、インフラストラクチャの現在の状態とコートで定義されている内容の差分を確認してから、差分を出力します。\n* `apply`により、`plan`の差分を適用して、状態を更新します。\n\n最初のラウンドでは状態は空で、その後、Terraformによって適用されたリソースの詳細（IDなど）が挿入されます。\n\n問題は、その状態がどこに保存されるかということです。また、複数のデベロッパーがコード上で共同作業を行えるようにするにはどうすればよいのでしょうか？\n\n解決策はとても簡単で、GitLabを利用して、[Terraform HTTPバックエンド](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html)を介して状態を保存して共有するだけです。\n\nこのバックエンドを使用するには、まずはもっともシンプルな`terraform/backend.tf`ファイルを作成します。次のステップは、パイプラインで処理します。\n\n```terraform\nterraform {\n  backend \"http\" {\n  }\n}\n```\n\nこれで、4つのリソースをデプロイするための最低限のTerraformコードができあがりました。変数の値は実行する際に指定するので、後でご説明します。\n\n### ワークフロー\n\nこれから以下のワークフローを実装します。\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    A(main) -->|新機能| B(feature_X)\n\n    B -->|自動デプロイ| C[review/feature_X]\n    B -->|マージ| D(main)\n    C -->|破棄| D\n\n    D -->|自動デプロイ| E[integration]\n    E -->|手動| F[qa]\n\n    D -->|タグ付け| G(X.Y.Z)\n    F -->|検証| G\n\n    G -->|自動デプロイ| H[staging]\n    H -->|手動| I{plan}\n    I -->|手動| J[production]\n\u003C/pre>\n\n1. **フィーチャー**ブランチを作成します。これにより、コードに対して継続的にすべてのスキャナーが実行され、コンプライアンスとセキュリティを確保できます。このコードは、現在のブランチの名前が付けられた一時的な環境`review/feature_branch`に継続的にデプロイされます。これは、デベロッパーと運用チームが誰にも影響を与えることなくコードをテストできる安全な環境です。また、ここでコードレビューやスキャナーの実行などのプロセスを実施し、コードの品質とセキュリティが許容範囲内であることを確認し、資産が危険にさらされることのないようにします。このブランチでデプロイされたインフラストラクチャは、ブランチが閉じられると自動的に破棄されます。これにより予算範囲内に収めやすくなります。\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    A(main) -->|新機能| B(feature_X)\n\n    B -->|自動デプロイ| C[review/feature_X]\n    B -->|マージ| D(main)\n    C -->|破棄| D\n\u003C/pre>\n\n2. 承認されると、フィーチャーブランチはmainブランチに**マージ**されます。これは[保護ブランチ](https://docs.gitlab.com/ee/user/project/protected_branches.html)であり、誰もプッシュできません。本番環境への変更リクエストをすべて十分にテストするために必要です。このブランチも継続的にデプロイされます。ここでのターゲットは`integration`環境です。この環境をもう少し安定させるために、削除は自動化されておらず、手動でトリガーできるようになっています。\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    D(main) -->|自動デプロイ| E[integration]\n\u003C/pre>\n\n3. ここから次のデプロイをトリガーするには、手動による承認が必要となります。これにより、mainブランチが`qa`環境にデプロイされます。ここでパイプラインからの削除を防ぐルールを設定します。何しろすでに3つ目のこの環境はかなり安定しているはずなので、このルールは誤って削除されるのを防ぐことを目的とします。貴社のプロセスに合わせて、お好きなようなルールを調整してください。\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    D(main)-->|自動デプロイ| E[integration]\n    E -->|手動| F[qa]\n\u003C/pre>\n\n4. 次に進むには、コードに**タグ付け**する必要があります。[保護タグ](https://docs.gitlab.com/ee/user/project/protected_tags.html)を使用して、特定のユーザーのみが最後の2つの環境にデプロイできるようにします。これにより、`staging`環境へのデプロイが即座にトリガーされます。\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    D(main) -->|タグ付け| G(X.Y.Z)\n    F[qa] -->|検証| G\n\n    G -->|自動デプロイ| H[staging]\n\u003C/pre>\n\n5. ついに`production`に到達しました。インフラストラクチャに関して言うと、（10%や25%など）段階的にデプロイするのは難しい場合が多いため、インフラストラクチャ全体をデプロイします。ただし、この最後のステップで行う手動トリガーで、このデプロイを制御します。そして、この極めて重要な環境を最大限に制御できるようにするために、[保護環境](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)として管理します。\n\n\u003Cpre class=\"mermaid\">\nflowchart LR\n    H[staging] -->|手動| I{plan}\n    I -->|手動| J[production]\n\u003C/pre>\n\n### パイプライン\n\n上記の[ワークフロー](#the-workflow)を実装するために、2つの[ダウンストリームパイプライン](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html)とともにパイプラインを構築します。\n\n#### メインパイプライン\n\nまずは、メインパイプラインから始めましょう。メインパイプラインは、**フィーチャーブランチへのプッシュ**、**デフォルトブランチへのマージ**、または**タグ付け**が発生すると、必ず自動的にトリガーされます。*このパイプライン*によって、`dev`、`integration`、`staging`環境に対する真の**継続的デプロイ**を実現できます。プロジェクトのルートにある`.gitlab-ci.yml`ファイルで宣言します。\n\n![リポジトリのターゲット](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750097033417.png)\n\n```yml\nStages:\n  - test\n  - environments\n\n.environment:\n  stage: environments\n  variables:\n    TF_ROOT: terraform\n    TF_CLI_ARGS_plan: \"-var-file=../vars/$variables_file.tfvars\"\n  trigger:\n    include: .gitlab-ci/.first-layer.gitlab-ci.yml\n    strategy: depend            # Wait for the triggered pipeline to successfully complete\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nreview:\n  extends: .environment\n  variables:\n    environment: review/$CI_COMMIT_REF_SLUG\n    TF_STATE_NAME: $CI_COMMIT_REF_SLUG\n    variables_file: review\n    TF_VAR_aws_resources_name: $CI_COMMIT_REF_SLUG  # Used in the tag Name of the resources deployed, to easily differenciate them\n  rules:\n    - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n\nintegration:\n  extends: .environment\n  variables:\n    environment: integration\n    TF_STATE_NAME: $environment\n    variables_file: $environment\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nstaging:\n  extends: .environment\n  variables:\n    environment: staging\n    TF_STATE_NAME: $environment\n    variables_file: $environment\n  rules:\n    - if: $CI_COMMIT_TAG\n\n#### TWEAK\n# This tweak is needed to display vulnerability results in the merge widgets.\n# As soon as this issue https://gitlab.com/gitlab-org/gitlab/-/issues/439700 is resolved, the `include` instruction below can be removed.\n# Until then, the SAST IaC scanners will run in the downstream pipelines, but their results will not be available directly in the merge request widget, making it harder to track them.\n# Note: This workaround is perfectly safe and will not slow down your pipeline.\ninclude:\n  - template: Security/SAST-IaC.gitlab-ci.yml\n#### END TWEAK\n\n```\n\nこのパイプラインは、`test`と`environments`の2つのステージのみを実行します。前者は、*TWEAK（微調整）*により、スキャナーを実行するために必要です。後者では、上記で定義したケース（ブランチへのプッシュ、デフォルトブランチへのマージ、タグ付け）ごとに異なる変数セットを持つ子パイプラインがトリガーされます。\n\nここで子パイプラインに[strategy:depend](https://docs.gitlab.com/ee/ci/yaml/index.html#triggerstrategy)キーワードで依存を追加します。これにより、デプロイの完了後にGitLabのパイプラインビューが更新されます。\n\nご覧のとおりベースとなるジョブが[無効になる](https://docs.gitlab.com/ee/ci/jobs/#hide-jobs)ように定義し、特定の変数とルールで拡張して、ターゲット環境ごとに単一のデプロイメントだけがトリガーされるようにしています。\n\n[定義済み変数](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)に加え、定義する必要がある新たな2つのエントリを使用します。\n1. 各環境[固有の変数](#the-variable-definitions)：`../vars/$variables_file.tfvars`\n2. [子パイプライン](#the-child-pipeline)。`.gitlab-ci/.first-layer.gitlab-ci.yml`で定義\n\nまずは、簡単な方、つまり変数の定義から始めましょう。\n\n### 変数の定義\n\nここでは、2つのソリューションを組み合わせてTerraformに変数を提供します。\n\n* 1つ目は、[.tfvarsファイル](https://developer.hashicorp.com/terraform/language/values/variables#variable-definitions-tfvars-files)を使用して、機密性の低い入力をすべて行う方法です。これはGitLab内に保存する必要があります。\n\n![Terraformに変数を提供するための1つ目のソリューション](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097034/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750097033419.png)\n\n* 2つ目は、プレフィックスに`TF_VAR`を付けた[環境変数](https://developer.hashicorp.com/terraform/language/values/variables#environment-variables)を使用する方法です。変数を挿入するこの2つ目の方法は、[変数をマスク](https://docs.gitlab.com/ee/ci/variables/#mask-a-cicd-variable)し、[保護](https://docs.gitlab.com/ee/ci/variables/#protect-a-cicd-variable)し、さらに[スコープの環境を設定する](https://docs.gitlab.com/ee/ci/environments/index.html#limit-the-environment-scope-of-a-cicd-variable)GitLabの機能とも関係する、**機密情報の漏えいを防ぐ**強力なソリューションです（本番環境のプライベートClassless Inter-Domain Routing（CIDR）で非常に機密性が高いデータをやり取りすると考えられる場合は、この方法で保護すれば、本番環境、および保護ブランチやタグに対して実行されるパイプラインでのみ利用できるようにし、ジョブのログでその値がマスクされるようにすることができます）。\n\n![Terraformに変数を提供するための2つ目のソリューション](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097034/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750097033422.png)\n\nまた、各変数ファイルを変更できるユーザーを設定するために、[`CODEOWNERS`ファイル](https://docs.gitlab.com/ee/user/project/codeowners/)で各変数ファイルを管理する必要があります。\n\n```\n[Production owners] \nvars/production.tfvars @operations-group\n\n[Staging owners]\nvars/staging.tfvars @odupre @operations-group\n\n[CodeOwners owners]\nCODEOWNERS @odupre\n```\n\nこの記事は、Terraformのトレーニング用ではないため、詳しく説明せず、ここでは`vars/review.tfvars`ファイルを紹介するだけに留めます。当然ながら、これに続く環境ファイルもほぼ同じです。ここでは機密性の低い変数とその値を設定するだけです。\n\n```shell\naws_vpc_cidr = \"10.1.0.0/16\"\naws_public_subnet_cidr = \"10.1.1.0/24\"\naws_private_subnet_cidr = \"10.1.2.0/24\"\n```\n\n#### 子パイプライン\n\n実際の作業はこのパイプライン内で行われます。そのため、最初のパイプラインよりも少し複雑です。しかしながら、力を合わせれば何でも乗り越えられます！\n\n[メインパイプライン](#the-main-pipeline)の定義で説明したように、ダウンストリームパイプラインは`.gitlab-ci/.first-layer.gitlab-ci.yml`で宣言されています。\n\n![ファイルで宣言されているダウンストリームパイプライン](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097033/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750097033424.png)\n\n小さなステップに分けて説明します。最後に全体像が見えるはずです。\n\n##### Terraformコマンドを実行してコードを保護する\n\nまずは、Terraformのパイプラインを実行したいと思います。GitLabはオープンソースであるため、Terraform用のテンプレートもオープンソースです。そのため、このテンプレートを含めるだけで済みます。以下のスニペットを使用して行えます。\n\n```yml\ninclude:\n  - template: Terraform.gitlab-ci.yml\n```\n\nこのテンプレートは、planとapplyが行われる前に、Terraformによるフォーマットのチェックとコードの検証を実行します。デプロイしたものを破棄することもできます。\n\nさらに、GitLabは統合された単一のDevSecOpsプラットフォームであるため、このテンプレート内に2つのセキュリティスキャナーを自動的に組み込み、コード内の潜在的な脅威を検出し、次の環境にデプロイされる前に警告を発します。\n\nこれでコードの確認、保護、ビルド、デプロイが完了したので、いくつかの便利な技をご紹介します。\n\n##### ジョブ間でキャッシュを共有する\n\nジョブの結果をキャッシュして、後続のパイプラインジョブで再利用します。これはとても簡単で、以下のコードを追加するだけで行えます。\n\n```yml\ndefault:\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: cache-$CI_COMMIT_REF_SLUG\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n```\n\nここでは、コミットごとに異なるキャッシュを定義し、必要に応じてmainブランチ名にフォールバックするようにします。\n\n使用しているテンプレートをよく見ると、ジョブの実行タイミングを制御するルールがあることがわかります。全ブランチですべての制御（QAとセキュリティの両方）を実行したいと思います。そのため、次にこれらの設定を上書きします。\n\n##### すべてのブランチで制御を実行する\n\nGitLabテンプレートは強力な機能で、テンプレートの一部のみを上書きできます。品質チェックとセキュリティチェックが必ず実行されるよう、一部のジョブのルールを上書きしたいと思います。これらのジョブ向けに定義するその他すべては、テンプレートで定義された内容のままにします。\n\n```yml\nfmt:\n  rules:\n    - when: always\n\nvalidate:\n  rules:\n    - when: always\n\nkics-iac-sast:\n  rules:\n    - when: always\n\niac-sast:\n  rules:\n    - when: always\n```\n\nこれで品質とセキュリティの制御を実施できたため、[ワークフロー](#the-workflow)内のメインの環境（integrationとstaging）とreview環境の動作に違いを付けたいと思います。まずはメインの環境の振る舞いを定義し、review環境用にこの設定を微調整していきましょう。\n\n##### integrationとstaging環境への継続的デプロイ\n\n前述のように、この2つの環境にmainブランチとタグをデプロイしたいため、そのように制御するルールを`build`と`deploy`の両方のジョブに追加します。そして、`integration`環境でのみ`destroy`を有効にします。`staging`環境は重要度が高いため、ワンクリックで削除できないようにします。この操作はエラーを引き起こしやすく、避けたいと考えています。\n\n最後に、`deploy`ジョブを`destroy`ジョブにリンクして、GitLab GUIから直接環境を`stop`できるようにします。\n\nここで使用する`GIT_STRATEGY`は、破棄する際にRunner内のソースブランチからコードが取得されることを防ぎます。これは、ブランチが手動で削除された場合は失敗するため、キャッシュを使用して、Terraformの命令を実行するために必要なものすべてを取得します。\n\n```yml\nbuild:  # terraform plan\n  environment:\n    name: $TF_STATE_NAME\n    action: prepare\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndeploy: # terraform apply --> automatically deploy on corresponding env (integration or staging) when merging to default branch or tagging. Second layer environments (qa and production) will be controlled manually\n  environment: \n    name: $TF_STATE_NAME\n    action: start\n    on_stop: destroy\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndestroy:\n  extends: .terraform:destroy\n  variables:\n    GIT_STRATEGY: none\n  dependencies:\n    - build\n  environment:\n    name: $TF_STATE_NAME\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $TF_DESTROY == \"true\" # Manually destroy integration env.\n      when: manual\n```\n前述のとおり、これは`integration`と`staging`環境へのデプロイというニーズに即しています。しかしながら、デベロッパーがほかの人に影響を及ぼさずに、自分のコードに触れて検証できる一時的な環境がまだ不足しています。そのため、次は`review`環境へのデプロイを行います。\n\n##### review環境への継続的デプロイ\n\nreview環境へのデプロイは、`integration`や`staging`環境へのデプロイと大差はありません。そこで、ここでもGitLabの機能を活用して、ジョブ定義の一部のみを上書きします。\n\nまずは、これらのジョブがフィーチャーブランチでのみ実行されるようルールを設定します。\n\n次に、`deploy_review`ジョブを`destroy_review`ジョブにリンクします。これにより、GitLabユーザーインターフェイスから**手動で**環境を停止できるようになりますが、さらに重要なのは、フィーチャーブランチの完了時に**環境の破棄が自動的にトリガー**されるようになります。これは、運用にかかる費用を抑えるのに効果的な、優れたFinOpsプラクティスです。\n\nTerraformでは、インフラストラクチャの構築時と同様に、破棄する際にもplanファイルが必要なため、`destroy_review`から`build_review`に依存を追加して、そのアーティファクトを取得します。\n\n最後に、ご覧のとおり、環境の名前を`$environment`に設定します。これは、[メインパイプライン](#the-main-pipeline)で`review/$CI_COMMIT_REF_SLUG`に設定され、`trigger:forward:yaml_variables:true`という命令により、その子パイプラインに転送されます。\n\n```yml\nbuild_review:\n  extends: build\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndeploy_review:\n  extends: deploy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: start\n    on_stop: destroy_review\n    # url: https://$CI_ENVIRONMENT_SLUG.example.com\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndestroy_review:\n  extends: destroy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   # Do not destroy staging\n      when: never\n    - when: manual\n```\n\nさて、まとめると、これで次のことを行うパイプラインができました。\n\n* 一時的なreview環境へのデプロイ。フィーチャーブランチの完了時に、自動的にクリーンアップされます\n* **デフォルトブランチ**から`integration`への継続的デプロイ\n* **タグ**から`staging`への継続的デプロイ\n\nさらにレイヤを追加し、今回は手動でのトリガーをもとに`qa`と`production`環境にデプロイされるようにしましょう。\n\n##### qaとproduction環境への継続的デプロイ\n\n誰もが本番環境に継続的デプロイしたいわけではないため、次の2つのデプロイには手動による検証を追加します。単に**CD**の観点で考えた場合、このトリガーを追加することはありませんが、ほかのトリガーからジョブを実行する方法を学ぶ機会として捉えてください。\n\nこれまでデプロイを実行する際は、必ず[メインパイプライン](#the-main-pipeline)から[子パイプライン](#the-child-pipeline)を開始してきました。\n\nデフォルトブランチとタグからさらにデプロイを実行したいため、これらの追加ステップ用に別のレイヤを追加します。新たな手順は必要ありません。[メインパイプライン](#the-main-pipeline)で行ったのとまったく同じプロセスを再度繰り返します。この方法だと、必要な数だけレイヤを操作できます。中には最大で9つの環境がある例も見たことがあります。環境の数を抑えることの利点についてはあらためて説明しませんが、このプロセスを使用することで、初期段階から最終的なデリバリーまで、同じパイプラインを非常に簡単に実装できます。その上、パイプラインの定義をシンプルに保ちつつ、コストをかけずに維持できる小さな塊に分割可能です。\n\nここでは変数の競合を防ぐために、新しいvar名を使用してTerraformの状態と入力ファイルを識別しています。\n\n```yml\n.2nd_layer:\n  stage: 2nd_layer\n  variables:\n    TF_ROOT: terraform\n  trigger:\n    include: .gitlab-ci/.second-layer.gitlab-ci.yml\n    # strategy: depend            # Do NOT wait for the downstream pipeline to finish to mark upstream pipeline as successful. Otherwise, all pipelines will fail when reaching the pipeline timeout before deployment to 2nd layer.\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nqa:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: qa\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nproduction:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: production\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_TAG\n```\n\n**ここで重要なテクニックは、新しいダウンストリームパイプラインに使用するstrategyの設定です。**`trigger:strategy`はデフォルトの値のままにしておきます。そうしなければ、[メインパイプライン](#the-main-pipeline)は、[孫パイプライン](#the-grand-child-pipeline)が完了するまで待機することになります。手動トリガーだと、非常に長い時間かかり、パイプラインダッシュボードが読みづらく、理解しにくくなる可能性があります。\n\nここでインクルードした`.gitlab-ci/.second-layer.gitlab-ci.yml`ファイルが何なのか疑問に感じた方もいらっしゃるかもしれません。こちらは次のセクションで説明します。\n\n##### 1つ目のレイヤのパイプラインに関する全定義\n\n1つ目のレイヤの全詳細（`.gitlab-ci/.first-layer.gitlab-ci.yml`に保存）を確認したい場合は、以下のセクションを参照してください。\n\n```yml\nvariables:\n  TF_VAR_aws_ami_id: $AWS_AMI_ID\n  TF_VAR_aws_instance_type: $AWS_INSTANCE_TYPE\n  TF_VAR_aws_default_region: $AWS_DEFAULT_REGION\n\ninclude:\n  - template: Terraform.gitlab-ci.yml\n\ndefault:\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: cache-$CI_COMMIT_REF_SLUG\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n\nstages:\n  - validate\n  - test\n  - build\n  - deploy\n  - cleanup\n  - 2nd_layer       # Use to deploy a 2nd environment on both the main branch and on the tags\n\nfmt:\n  rules:\n    - when: always\n\nvalidate:\n  rules:\n    - when: always\n\nkics-iac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: on_success\n\niac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: on_success\n\n###########################################################################################################\n## Integration env. and Staging. env\n##  * Auto-deploy to Integration on merge to main.\n##  * Auto-deploy to Staging on tag.\n##  * Integration can be manually destroyed if TF_DESTROY is set to true.\n##  * Destroy of next env. is not automated to prevent errors.\n###########################################################################################################\nbuild:  # terraform plan\n  environment:\n    name: $TF_STATE_NAME\n    action: prepare\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndeploy: # terraform apply --> automatically deploy on corresponding env (integration or staging) when merging to default branch or tagging. Second layer environments (qa and production) will be controlled manually\n  environment: \n    name: $TF_STATE_NAME\n    action: start\n    on_stop: destroy\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG\n\ndestroy:\n  extends: .terraform:destroy\n  variables:\n    GIT_STRATEGY: none\n  dependencies:\n    - build\n  environment:\n    name: $TF_STATE_NAME\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $TF_DESTROY == \"true\" # Manually destroy integration env.\n      when: manual\n###########################################################################################################\n\n###########################################################################################################\n## Dev env.\n##  * Temporary environment. Lives and dies with the Merge Request.\n##  * Auto-deploy on push to feature branch.\n##  * Auto-destroy on when Merge Request is closed.\n###########################################################################################################\nbuild_review:\n  extends: build\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndeploy_review:\n  extends: deploy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: start\n    on_stop: destroy_review\n    # url: https://$CI_ENVIRONMENT_SLUG.example.com\n  rules:\n    - if: $CI_COMMIT_TAG\n      when: never\n    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH\n      when: on_success\n\ndestroy_review:\n  extends: destroy\n  dependencies:\n    - build_review\n  environment:\n    name: $environment\n    action: stop\n  rules:\n    - if: $CI_COMMIT_TAG  # Do not destroy production\n      when: never\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH   # Do not destroy staging\n      when: never\n    - when: manual\n###########################################################################################################\n\n###########################################################################################################\n## Second layer\n##  * Deploys from main branch to qa env.\n##  * Deploys from tag to production.\n###########################################################################################################\n.2nd_layer:\n  stage: 2nd_layer\n  variables:\n    TF_ROOT: terraform\n  trigger:\n    include: .gitlab-ci/.second-layer.gitlab-ci.yml\n    # strategy: depend            # Do NOT wait for the downstream pipeline to finish to mark upstream pipeline as successful. Otherwise, all pipelines will fail when reaching the pipeline timeout before deployment to 2nd layer.\n    forward:\n      yaml_variables: true      # Forward variables defined in the trigger job\n      pipeline_variables: true  # Forward manual pipeline variables and scheduled pipeline variables\n\nqa:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: qa\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n\nproduction:\n  extends: .2nd_layer\n  variables:\n    TF_STATE_NAME_2: production\n    environment: $TF_STATE_NAME_2\n    TF_CLI_ARGS_plan_2: \"-var-file=../vars/$TF_STATE_NAME_2.tfvars\"\n  rules:\n    - if: $CI_COMMIT_TAG\n###########################################################################################################\n```\n\nこの段階で、すでに3つの環境に問題なくデプロイしています。個人的にはこのアプローチが理想的でおすすめです。ただし、もっと多くの環境が必要であれば、CDパイプラインに追加してください。\n\n`trigger:include`というキーワードでダウンストリームパイプラインをインクルードしていることはすでにお気づきだと思います。これにより、`.gitlab-ci/.second-layer.gitlab-ci.yml`ファイルがインクルードされます。ほぼ同じパイプラインを実行したいため、当然ながら先ほど詳しく説明したものと内容は非常に似ています。ここで[孫パイプライン](#the-grand-child-pipeline)を定義する主な利点は、それ自体が独立しているため、変数やルールを非常に定義しやすくことです。\n\n### 孫パイプライン\n\nこの2つ目のレイヤとなるパイプラインは、まったく新しいパイプラインです。そのため、1つ目のレイヤの定義を模倣しつつ、以下を行う必要があります。\n\n* [Terraformテンプレートのインクルード](#run-terraform-commands-and-secure-the-code)。\n* [セキュリティチェックの実施](#run-controls-on-all-branches)。Terraformの検証は1つ目のレイヤと重複するものの、セキュリティスキャナーにより以前にスキャナーが実行されたときにはまだ存在していなかった脅威を見つけられる可能性があります（stagingへのデプロイの数日後にproductionへのデプロイを行う場合など）。\n* [buildとdeployジョブを上書きして特定のルールを設定](#cd-to-review-environments)。早すぎる削除を防ぐために、`destroy`ステージは自動化されないようになったことにご注意ください。\n\n上述のとおり、`TF_STATE_NAME`と`TF_CLI_ARGS_plan`は、[メインパイプライン](#the-main-pipeline)から[子パイプライン](#the-child-pipeline)に渡されています。これらの値を[子パイプライン](#the-child-pipeline)から[孫パイプライン](#the-grand-child-pipeline)に渡すには、別の変数名が必要でした。そのため、子パイプラインでは変数名の末尾に`_2`を付け足し、`before_script`の実行中に適切な変数に値をコピーしています。\n\n各ステップについては説明済みであるため、ここでは細かいところは省き、直接グローバルな2つ目のレイヤの定義（`.gitlab-ci/.second-layer.gitlab-ci.yml`に保存）の全体像をご確認ください。\n\n```yml\n# Use to deploy a second environment on both the default branch and the tags.\n\ninclude:\n  template: Terraform.gitlab-ci.yml\n\nstages:\n  - validate\n  - test\n  - build\n  - deploy\n\nfmt:\n  rules:\n    - when: never\n\nvalidate:\n  rules:\n    - when: never\n\nkics-iac-sast:\n  rules:\n    - if: $SAST_DISABLED == 'true' || $SAST_DISABLED == '1'\n      when: never\n    - if: $SAST_EXCLUDED_ANALYZERS =~ /kics/\n      when: never\n    - when: always\n\n###########################################################################################################\n## QA env. and Prod. env\n##  * Manually trigger build and auto-deploy in QA\n##  * Manually trigger both build and deploy in Production\n##  * Destroy of these env. is not automated to prevent errors.\n###########################################################################################################\nbuild:  # terraform plan\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: $TF_STATE_NAME_2\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n  environment:\n    name: $TF_STATE_NAME_2\n    action: prepare\n  before_script:  # Hack to set new variable values on the second layer, while still using the same variable names. Otherwise, due to variable precedence order, setting new value in the trigger job, does not cascade these new values to the downstream pipeline\n    - TF_STATE_NAME=$TF_STATE_NAME_2\n    - TF_CLI_ARGS_plan=$TF_CLI_ARGS_plan_2\n  rules:\n    - when: manual\n\ndeploy: # terraform apply\n  cache:  # Use a shared cache or tagged runners to ensure terraform can run on apply and destroy\n    - key: $TF_STATE_NAME_2\n      fallback_keys:\n        - cache-$CI_DEFAULT_BRANCH\n      paths:\n        - .\n  environment: \n    name: $TF_STATE_NAME_2\n    action: start\n  before_script:  # Hack to set new variable values on the second layer, while still using the same variable names. Otherwise, due to variable precedence order, setting new value in the trigger job, does not cascade these new values to the downstream pipeline\n    - TF_STATE_NAME=$TF_STATE_NAME_2\n    - TF_CLI_ARGS_plan=$TF_CLI_ARGS_plan_2\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n    - if: $CI_COMMIT_TAG && $TF_AUTO_DEPLOY == \"true\"\n    - if: $CI_COMMIT_TAG\n      when: manual\n###########################################################################################################\n```\n\nこれで**準備完了です。** 本番環境にデプロイする前に、ジョブの実行を管理する方法は自由に変更できます。たとえば、GitLabの機能を活用して、本番環境へのデプロイ前に[ジョブを遅延させる](https://docs.gitlab.com/ee/ci/jobs/job_control.html#run-a-job-after-a-delay)設定をすることも可能です。\n\n## 実際に試す\n\nついに目標を達成できました。**フィーチャーブランチ**、**mainブランチ**、**タグ**だけで、**5つの異なる環境へのデプロイ**を管理できるようになりました。\n* パイプラインの効率とセキュリティを確保するために、GitLabのオープンソーステンプレートを集中的に再利用しました。\n* GitLabテンプレートの機能を活用して、個別に制御が必要なブロックだけを上書きしました。\n* パイプラインを小さな塊に分割し、ニーズに完全に合うようにダウンストリームパイプラインを制御しました。\n\nここからは、自由に進めてください。たとえば、[trigger:rules:changes](https://docs.gitlab.com/ee/ci/yaml/#ruleschanges)キーワードを使って、ソフトウェアのソースコードのダウンストリームパイプラインをトリガーするように、メインパイプラインを簡単に更新することも可能です。また、発生した変更に応じて、別の[テンプレート](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/)を使用できます。その方法はまた別の機会に。",[111,835,836,793,684],"CI","CD","2025-06-12",{"slug":839,"featured":6,"template":686},"using-child-pipelines-to-continuously-deploy-to-five-environments","content:ja-jp:blog:using-child-pipelines-to-continuously-deploy-to-five-environments.yml","Using Child Pipelines To Continuously Deploy To Five Environments","ja-jp/blog/using-child-pipelines-to-continuously-deploy-to-five-environments.yml","ja-jp/blog/using-child-pipelines-to-continuously-deploy-to-five-environments",{"_path":845,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":846,"content":852,"config":858,"_id":860,"_type":16,"title":861,"_source":18,"_file":862,"_stem":863,"_extension":21},"/ja-jp/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way",{"title":847,"description":848,"ogTitle":847,"ogDescription":848,"noIndex":6,"ogImage":849,"ogUrl":850,"ogSiteName":700,"ogType":701,"canonicalUrls":850,"schema":851},"モノレポ用のGitLab CI/CDパイプラインを簡単に構築する方法","単一のリポジトリで複数のアプリケーションをホストするモノレポ用に、GitLab CI/CDパイプラインを作成する方法についてご紹介します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660151/Blog/Hero%20Images/blog-image-template-1800x945__26_.png","https://about.gitlab.com/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"モノレポ用のGitLab CI/CDパイプラインを簡単に構築する方法\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Sam Morris\"}],\n        \"datePublished\": \"2024-07-30\",\n      }",{"title":847,"description":848,"authors":853,"heroImage":849,"date":855,"body":856,"category":14,"tags":857},[854],"Sam Morris","2024-07-30","モノレポを使用すると、単一のリポジトリで複数のアプリケーションのコードをホストできます。GitLabでこれを実現しようとすると、プロジェクト内の各ディレクトリに異なるアプリケーションのソースコードを配置することになります。この方法だとコードの保存場所をバージョン管理できるものの、GitLabの[CI/CD](https://about.gitlab.com/ja-jp/topics/ci-cd/)パイプライン機能を最大限に活用するのは困難でした。しかしながら、新たな方法が登場しました！\n\n## モノレポにおけるCI/CDの理想的な実例\n\n通常、リポジトリには複数のアプリケーションのコードが格納されているため、複数のパイプライン設定が必要となります。たとえば、.NETアプリケーションとSpringアプリケーションがあるプロジェクトの場合、アプリケーションごとに異なるビルドジョブとテストジョブを実施している可能性があります。この場合、パイプラインを完全に切り離し、特定のアプリケーションのソースコードの変更が発生した場合のみ、各パイプラインを実行するのが理想的です。\n\nこのようなプロセスを技術的に実現するには、特定のディレクトリの変更に基づいて特定のYAMLファイルをインクルードする、プロジェクトレベルのパイプライン設定ファイル`.gitlab-ci.yml`を用意します。`.gitlab-ci.yml`パイプラインは、コードに加えられた変更に基づき、適切なパイプラインをトリガーするコントロールプレーンとして機能します。\n\n## 従来のアプローチ\n\nGitLab 16.4より前のバージョンでは、プロジェクト内のディレクトリまたはファイルへの変更に基づいてYAMLファイルをインクルードすることはできませんでした。ただし、回避策を使えばこの機能を実現することは可能でした。\n\nこれからご紹介するモノレポプロジェクトの例では、異なるアプリケーション用に2つのディレクトリがあるとします。それぞれJavaアプリ用の`java`ディレクトリとPythonアプリ用の`python`ディレクトリがあります。それぞれのディレクトリには、各アプリをビルドするためのアプリケーション固有のYAMLファイルが含まれています。シンプルにプロジェクトのパイプラインファイルに両アプリケーションのパイプラインファイルをインクルードし、それらのファイルで直接ロジック処理を行います。\n\n`.gitlab-ci.yml`：\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\ntop-level-job:\n  stage: build\n  script:\n    - echo \"Hello world...\"\n\ninclude:\n  - local: '/java/j.gitlab-ci.yml'\n  - local: '/python/py.gitlab-ci.yml'\n\n```\n\nアプリケーション固有の各パイプラインファイルで「.java-common」もしくは「.python-common」という名前の非表示ジョブを作成します。これらのジョブは対応するアプリのディレクトリに変更が加えられた場合にのみ実行されます。デフォルトでは[非表示ジョブ](https://docs.gitlab.com/ee/ci/jobs/#hide-jobs)は実行されず、通常は特定のジョブ設定を再利用するために使用されます。各パイプラインは、非表示ジョブを拡張して変更がないか監視するファイルを定めたルールを継承してから、パイプラインジョブを開始します。\n\n`j.gitlab-ci.yml`：\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\n.java-common:\n  rules:\n    - changes:\n      - '../java/*'\n\njava-build-job:\n  extends: .java-common\n  stage: build\n  script:\n    - echo \"Javaのビルド\"\n\njava-test-job:\n  extends: .java-common\n  stage: test\n  script:\n    - echo \"Javaのテスト\"\n\n```\n\n`py.gitlab-ci.yml`：\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\n.python-common:\n  rules:\n    - changes:\n      - '../python/*'\n\npython-build-job:\n  extends: .python-common\n  stage: build\n  script:\n    - echo \"Pythonのビルド\"\n\npython-test-job:\n  extends: .python-common\n  stage: test\n  script:\n    - echo \"Pythonのテスト\"\n\n```\n\nこの方法にはいくつかのデメリットがあります。たとえば、確実にルールに準拠するために、YAMLファイル内の他のジョブ用にそれぞれジョブを拡張しなければならないため、多くの冗長なコードが発生し、ヒューマンエラーが起きやすくなります。さらに拡張されたジョブでは重複するキーは持てないため、各ジョブにおいて独自の`rules`ロジックを定義できません。定義しようとした場合、キーの競合が発生し、[キーの値はマージされません](https://docs.gitlab.com/ee/ci/yaml/index.html#extends)。\n\n結果として、`java/`が更新されると、j.gitlab-ci.ymlジョブを含むパイプラインが実行され、`python/`が更新されると、py.gitlab-ci.ymlジョブを含むパイプラインが実行されます。\n\n## 新たなアプローチ：パイプラインファイルを条件付きでインクルードする\n\n\u003C!-- 空白行 -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/6phvk8jioAo?si=y6ztZODvUtM-cHmZ\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- 空白行 -->\n\nGitLab 16.4では、[パイプライン向けに`rules:changes`を含む`include`](https://docs.gitlab.com/ee/ci/yaml/includes.html#include-with-ruleschanges)が導入されました。それまでは`include`に`rules:if`を使用することはできたものの、`rules:changes`は使用できませんでした。これは非常に強力なアップデートです。これにより、プロジェクトのパイプライン設定で`include`キーワードを使用するだけで、モノレポのルールを定義できるようになりました。\n\n新たな`.gitlab-ci.yml`：\n\n```\nstages:\n  - build\n  - test\n\ntop-level-job:\n  stage: build\n  script:\n    - echo \"Hello world...\"\n\ninclude:\n  - local: '/java/j.gitlab-ci.yml'\n    rules:\n      - changes:\n        - 'java/*'\n  - local: '/python/py.gitlab-ci.yml'\n    rules:\n      - changes:\n        - 'python/*'\n\n```\n\nその後、各アプリケーションのYAMLファイルにおいて非表示ジョブを何度も拡張せずに済むため、アプリケーションコードのビルドとテストだけに集中できます。これによって、より柔軟にジョブを定義できるようになり、エンジニアによるコードの書き直し作業が軽減します。\n\n新たな`j.gitlab-ci.yml`：\n\n```\nstages:\n  - build\n  - test\n  - deploy\n\njava-build-job:\n  stage: build\n  script:\n    - echo \"Javaのビルド\"\n\njava-test-job:\n  stage: test\n  script:\n    - echo \"Javaのテスト\"\n\n```\n\n新たな`py.gitlab-ci.yml`：\n```\nstages:\n  - build\n  - test\n  - deploy\n\npython-build-job:\n  stage: build\n  script:\n    - echo \"Pythonのビルド\"\n\npython-test-job:\n  stage: test\n  script:\n    - echo \"Pythonのテスト\"\n\n```\n\n上記の設定により、JavaとPythonのディレクトリがそれぞれ変更された場合にのみ、JavaまたはPythonのジョブをインクルードするという同じタスクを実行できます。実装時に考慮すべき点は、[`changes`を使用すると、ジョブが予期せぬタイミングで実行される可能性がある](https://docs.gitlab.com/ee/ci/jobs/job_troubleshooting.html#jobs-or-pipelines-run-unexpectedly-when-using-changes)ということです。新しいブランチやタグをGitLabにプッシュすると、changesルールは必ず「true」と評価されるため、`rules:changes`の定義内容にかかわらず、ブランチへの最初のプッシュ時に、含まれるすべてのジョブが実行されます。こういった事態がなるべく起こらないようにするために、まずはフィーチャーブランチを作成してからマージリクエストを開いて開発を始めることをおすすめします。ブランチの作成時に最初にプッシュすることで、すべてのジョブが強制的に実行されるためです。\n\n総括すると、モノレポはGitLabおよびCI/CDと組み合わせて、戦略的に利用できる手法です。新たな`rules:changes`機能を含む`include`キーワードの登場により、GitLab CIにおいてモノレポを使う際に適用できる優れたベストプラクティスができました。モノレポの利用をお考えの場合は、ぜひGitlab Ultimateの無料トライアルをご利用ください。\n\n## CI/CDに関するその他のリソース\n\n* [GitLabでモノレポを管理するためのヒント5選](https://about.gitlab.com/blog/tips-for-managing-monorepos-in-gitlab/)\n* [CI/CDについて素早く学ぶ方法](https://about.gitlab.com/blog/how-to-learn-ci-cd-fast/)",[111,684],{"slug":859,"featured":6,"template":686},"building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way","content:ja-jp:blog:building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way.yml","Building A Gitlab Ci Cd Pipeline For A Monorepo The Easy Way","ja-jp/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way.yml","ja-jp/blog/building-a-gitlab-ci-cd-pipeline-for-a-monorepo-the-easy-way",{"_path":865,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":866,"content":872,"config":880,"_id":882,"_type":16,"title":883,"_source":18,"_file":884,"_stem":885,"_extension":21},"/ja-jp/blog/demystifying-ci-cd-variables",{"title":867,"description":868,"ogTitle":867,"ogDescription":868,"noIndex":6,"ogImage":869,"ogUrl":870,"ogSiteName":700,"ogType":701,"canonicalUrls":870,"schema":871},"GitLabの環境変数をわかりやすく解説","CI/CD変数はジョブやパイプラインを制御するのに便利（かつ柔軟に利用可能）なツールです。この記事では、GitLabの環境変数について知っておくべき情報をすべてご紹介します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664679/Blog/Hero%20Images/blog-image-template-1800x945__24_.png","https://about.gitlab.com/blog/demystifying-ci-cd-variables","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLabの環境変数をわかりやすく解説\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Veethika Mishra\"}],\n        \"datePublished\": \"2021-04-09\",\n      }",{"title":867,"description":868,"authors":873,"heroImage":869,"date":875,"body":876,"category":14,"tags":877,"updatedDate":879},[874],"Veethika Mishra","2021-04-09","[CI/CD](https://about.gitlab.com/ja-jp/topics/ci-cd/)変数は、さまざまな方法で定義・使用でき、高い柔軟性を持っています。変数はジョブやパイプラインを制御する上で非常に便利で、`.gitlab-ci.yml`設定ファイルに値をハードコーディングせずに済みます。このブログ記事では、変数のスコープや機能を分かりやすくお伝えするため、変数の定義や使い方に関する情報を網羅的に整理し、全体像をご紹介します。記事全体をとおして、関連するドキュメントがリンクされています。\n\n[GitLab CI/CD](https://docs.gitlab.com/ee/ci/)では、値を定義して保存することで、変数を使用してジョブをカスタマイズできます。変数を使用すれば、値をハードコーディングする必要はありません。GitLabでCI/CD変数を定義するには、**「設定」>>「CI/CD」>>「変数」**の順に移動します。または`.gitlab-ci.yml`ファイルで定義することも可能です。\n\n変数は、異なるデプロイ環境（`testing`、`staging`、`production`など）におけるサードパーティサービスの設定に役立ちます。それらの環境に紐づけられたサービスは、必要なAPIエンドポイントを指す変数を変更するだけで、簡単に変更できます。また、変数を使用してジョブを設定し、ジョブ実行時にジョブ内で環境変数として利用できるようにすることも可能です。\n\n![GitLabは、.gitlab-ci.ymlファイルを読み込んで、参照される変数をスキャンし、GitLab Runnerにその情報を送信します。変数情報はRunnerに渡され、Runnerによって出力されます。](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variables_processing.jpeg)\n\n## 変数と環境の関係\n\nソフトウェア開発プロセスには、製品をユーザー向けにリリースする前にテストするステージが含まれます。[環境](https://docs.gitlab.com/ee/ci/environments/)は、これらのステージの内容を定義するために使用されるもので、チームや組織によって異なる可能性があります。\n\n一方、変数とは、ユーザーによる製品の操作によって変化する可能性のあるデータ値を指します。これには、年齢や好み、またはタスクフローにおける次のステップを決定する要素となるあらゆる入力が該当します。\n\n[環境変数](https://docs.gitlab.com/ee/administration/environment_variables.html)という言葉は、皆さんもよく耳にされると思います。これは、ある環境で定義されているものの、アプリケーションの外部に存在する変数を指します。GitLab CI/CD変数を使用すると、デベロッパーはコード内で値を設定できます。変数の使用には、コードの柔軟性が保証されるという利点があります。GitLab CI/CD変数を使用すれば、コードに変更を加えることなく、特定の環境にデプロイされたアプリケーションを変更できます。これにより、アプリケーションの外部で設定の環境変数を変更するだけで、テストの実行やサードパーティサービスの統合を簡単に行えます。\n\n## CI/CD変数のスコープ\n\n![CI/CD変数の優先順位：1) 手動によって実行、トリガー、スケジュールされたパイプライン変数、2) プロジェクトレベル、グループレベル、インスタンスレベルの保護変数、3) 継承されたCI/CD変数、4) ymlに定義された、ジョブレベルのグローバル変数、5) デプロイ変数、6) 定義済みのCI/CD変数](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variables_precedence.jpeg)\n\n### `.gitlab-ci.yml`に定義された変数\n\nGitLabには、ジョブ環境で利用する必要がある変数を追加できます。これらのCI/CD変数は、`.gitlab-ci.yml`ファイルのデータベースURLのような、機密性の低いプロジェクト設定を保存するために使用されます。この変数は、複数のジョブやスクリプトで再利用でき、必要な場所で値を参照できます。値を変更する場合は、変数を一度更新するだけで、変数が使用されているすべての箇所に変更が反映されます。\n\n### プロジェクトのCI/CD変数\n\nリポジトリ固有の要件に縛られることなく、[プロジェクト設定](https://docs.gitlab.com/ee/ci/variables/#for-a-project)でCI/CD変数を定義できます。これにより、CI/CDパイプラインで利用できるようになります。これらの変数は、リポジトリの外部（`.gitlab-ci.yml`ファイルには保存されません）に保存されますが、CI/CDの設定やスクリプトで引き続き利用可能です。変数を`.gitlab-ci.yml`ファイル外に保存することで、これらの値のスコープをプロジェクト内のみに限定し、プロジェクトにプレーンテキストとして保存されることを防ぎます。\n\n### グループおよびインスタンスのCI/CD変数\n\n一部の変数は、グループレベル、あるいはインスタンスレベルで適用でき、グループやインスタンス内のすべてのプロジェクトで有用となる可能性があります。[グループまたはインスタンス設定](https://docs.gitlab.com/ee/ci/variables/#for-a-group)で変数を定義することで、それらのスコープ内にあるすべてのプロジェクトにおいて、実際の値がわからなくても、変数を使用できるようになります。下位スコープの変数を作成する必要もありません。たとえば、複数のプロジェクトにおいて更新が必要な共通の値がある場合、1か所で最新の状態に保つことで管理しやすくなります。また、パスワードの値を実際に知らなくても、複数のプロジェクトで特定のパスワードを使用することも可能です。\n\n## 環境としてのジョブとパイプライン\n\nGitLab CI/CDの変数は、環境変数としてだけでなく、`.gitlab-ci.yml`設定ファイル内でパイプラインの動作を設定するためにも使用されます。この場合、特定の環境に依存しない状況でも利用できます。また、プロジェクト、グループ、インスタンスの設定に保存しておくことで、パイプライン内のジョブで利用可能になります。\n\n以下に例を示します。\n\n```  \njob:  \n  rules:  \n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH  \n  script:  \n  - echo \"This job ran on the $CI_COMMIT_BRANCH branch.\"  \n```\n\nスクリプトセクション内で使用されている変数（例：`$CI_COMMIT_BRANCH`）は、定義されたジョブのスコープ内で実行されます。このスコープは「ジョブ環境」と呼ばれます。つまり、ジョブが開始されると、GitLab RunnerはDockerコンテナを起動し、その環境でジョブを実行します。Runnerはその変数（および他のすべての定義済み変数やカスタム変数）をジョブに提供します。さらに、その値をログ出力に表示することも可能です。\n\nただし、この変数は、ジョブの実行タイミングを決定するために、`if:`セクション**でも**使用されます。ただし、そのセクション自体は環境ではないため、これらの変数を「CI/CD変数」と呼びます。CI/CDジョブを動的に設定する際に使用できるのは**もちろん**、ジョブの実行時に環境変数としても利用できます。\n\n## 定義済み変数\n\nGitLab CI/CDパイプラインが開始されたタイミングで、[定義済み変数](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)がすでに存在します。ユーザーは変数自体を定義せずに、コミットやプロジェクト、パイプラインの詳細などの値にすぐにアクセスできます。\n\n## カスタムCI/CD変数\n\n![Runnerは、2種類のカスタムCI/CD変数（タイプとファイル）を作成できます。](https://about.gitlab.com/images/blogimages/demystifying-ci-cd-variables/variable_types.jpeg)\n\nGitLabでは、設定でCI/CD変数を作成する際に、変数に対してより詳細な設定オプションを利用できます。次のような追加の設定オプションを使用して、機密性の高い変数をより厳密に管理することが可能です。\n\n**環境スコープ**：ある変数を特定の環境でのみ使用する必要がある場合に、その環境でのみ使用できるように設定します。たとえば、デプロイトークンを`production`環境でのみ使用できるように設定できます。\n\n**保護変数**：環境スコープと同様に、デフォルトブランチなどの保護ブランチでパイプラインが実行される場合にのみ、変数を使用できるように設定できます。\n\n**変数タイプ**：一部のアプリケーションでは、設定をファイル形式で渡す必要があります。そうした設定が必要なアプリケーションを利用する場合は、変数タイプを「File」に設定します。この方法でCI/CD変数を設定する場合、Runnerが環境内で変数を利用できるようにする際に、実際に一時ファイルに変数を書き出し、そのファイルパスを変数の値として保存します。その後、アプリケーションに必要なファイルパスを渡すことで設定が適用されます。\n\nご紹介した変数の定義方法や使用方法に加えて、GitLabでは、手動でパイプラインを実行する必要がある場合に、事前入力済みの変数を生成する機能が導入されました。事前入力済みの変数が生成されることで、エラーの発生リスクが軽減され、パイプラインを実行しやすくなります。\n\n**マスクされた変数**：[マスクされた変数](https://docs.gitlab.com/ee/ci/variables/#mask-a-cicd-variable)は、変数の値が表示されないように**ジョブログに隠された**CI変数です。\n\n**マスクおよび非表示化された変数**：[GitLab 17.4](https://about.gitlab.com/ja-jp/blog/gitlab-17-4-released/)で導入された[マスクおよび非表示化された](https://docs.gitlab.com/ee/ci/variables/#hide-a-cicd-variable)変数は、ジョブログと同じマスキング機能を利用し、**設定UI**でも**値を非表示**にします。これらの変数を機密データ（シークレットなど）に使用した場合、誤って公開されてしまう可能性があるため、推奨されません。\n\n## シークレット\n\nシークレットとは、機密性が高く、秘密に保つべき認証情報のことを指し、以下のようなものが該当します。\n\n* パスワード\n* SSH鍵\n* アクセストークン\n* その他、漏洩すると組織に害を及ぼす可能性のある認証情報\n\nGitLabでは現在、キーやトークン、その他のシークレットをプロジェクトレベルで安全に管理するために、HashiCorp Vault、Google Cloud Secret Manager、Azure Key Vaultを活用できます。これにより、[CIで外部シークレットを使用](https://docs.gitlab.com/ee/ci/secrets/)することが可能です。そのため、セキュリティ上の理由から、これらのシークレットを他のCI/CD変数から分離して管理できます。\n\n### GitLabシークレットマネージャー\n\nGitLabでは、CIにおける外部シークレットのサポートに加えて、GitLab内でシークレットを安全かつ便利に保存するための[ネイティブなシークレット管理ソリューション](https://gitlab.com/groups/gitlab-org/-/epics/10108)の導入にも取り組んでいます。このソリューションは、お客様がGitLab固有のコンポーネントや環境で保存されたシークレットを使用したり、ネームスペースグループやプロジェクトレベルでのアクセスを簡単に管理したりする上でも役立ちます。\n\n## 関連リンク\n* [GitLabネイティブシークレットマネージャーでソフトウェアサプライチェーンのセキュリティを強化](https://about.gitlab.com/blog/gitlab-native-secrets-manager-to-give-software-supply-chain-security-a-boost/)\n\n***免責事項**：このブログには、今後リリース予定の製品、機能、および機能性に関する情報が記載されています。ただし、それらの情報はあくまで参考のために提供されているため、購入や計画の判断材料として使用することはお控えください。すべてのプロジェクトと同様に、このブログおよびリンク先のページに記載されている項目は、変更または遅延される場合があります。製品、機能、機能性の開発、リリース、およびタイミングに関する決定権は、GitLabに帰属します。*\n",[836,681,878,835,111,684],"inside GitLab","2025-01-13",{"slug":881,"featured":6,"template":686},"demystifying-ci-cd-variables","content:ja-jp:blog:demystifying-ci-cd-variables.yml","Demystifying Ci Cd Variables","ja-jp/blog/demystifying-ci-cd-variables.yml","ja-jp/blog/demystifying-ci-cd-variables",{"_path":887,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":888,"content":894,"config":904,"_id":906,"_type":16,"title":907,"_source":18,"_file":908,"_stem":909,"_extension":21},"/ja-jp/blog/we-need-to-talk-no-proxy",{"title":889,"description":890,"ogTitle":889,"ogDescription":890,"noIndex":6,"ogImage":891,"ogUrl":892,"ogSiteName":700,"ogType":701,"canonicalUrls":892,"schema":893},"no_proxyを標準化する方法：お客様事例で徹底解説","環境変数“no proxy”が原因で問題発生したことは？お客様事例を取り上げ、標準化の方法を考えてみました。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659507/Blog/Hero%20Images/AdobeStock_623844718.jpg","https://about.gitlab.com/blog/we-need-to-talk-no-proxy","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"no_proxyを標準化する方法：お客様事例で徹底解説\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Stan Hu\"}],\n        \"datePublished\": \"2021-01-27\",\n      }",{"title":889,"description":890,"authors":895,"heroImage":891,"date":897,"body":898,"category":14,"tags":899,"updatedDate":903},[896],"Stan Hu","2021-01-27","ウェブプロキシサーバーを使用した経験がある方なら、環境変数`http_proxy`や`HTTP_PROXY`をよくご存知でしょう。しかし、`no_proxy`（ノープロキシ）に関しては、どうもわかりにくい、と感じていらっしゃる方も多いのではないでしょうか。\n\nno proxyとは、あるホスト宛のトラフィックでプロキシを経由させないようにする環境変数です。世界基準が存在するHTTPと違い、ウェブクライアントがno proxyを処理する方法に「標準」は存在しません。その結果、ウェブクライアントは場合により異なる方法で処理を行います。\n\nその違いが原因でサービスが通信を停止し、その原因を突き止めるために週末返上で作業する羽目になったGitLabのお客様もいらっしゃいます。\n\nそこで、この記事ではGitLabのお客様が直面した問題について、具体例を挙げながら根本原因を探り、「no proxyを標準化する方法」というテーマを掘り下げてみます。\n\n### no proxyはなぜ「わかりにくい」のか\n\nno proxyがなぜわかりにくいのか、具体例を挙げて説明します。\n\n現在、ほとんどのウェブクライアントは環境変数を介してプロキシサーバーへの接続をサポートしています。環境変数には大文字表記と小文字表記があります。\n\n- `http_proxy` / `HTTP_PROXY`\n- `https_proxy` / `HTTPS_PROXY`\n- `no_proxy` / `NO_PROXY`\n\nこれらの変数は、プロキシサーバーにアクセスするのにどのURLを使用するか、またどういった例外を作っているか、クライアントに指示するものです。\n\nたとえば、ある企業で田中さんが`http://tanaka.example.com:8080` でリッスンしているプロキシサーバーの場合、次のようになります。\n\n```sh\nexport http_proxy=http://tanaka.example.com:8080\n```\n\n一方、同僚の斎藤さんも、次のように大文字バージョンの`HTTP_PROXY` で定義していたとします。\n\n```sh\nexport HTTP_PROXY=http://saito.example.com:8080\n```\n\nこの場合、どちらのプロキシサーバーが使用されることになるのでしょうか？答えは「状況によって異なる」です。ある場合は田中さんのプロキシサーバーが有効になる場合もあれば、ある場合は斎藤さんのプロキシサーバーが有効になる場合があります。\n\nこの場合、どちらのプロキシサーバーが使用されることになるのでしょうか？答えは「状況によって異なる」です。ある場合は田中さんのプロキシサーバーが有効になる場合もあれば、ある場合は斎藤さんのプロキシサーバーが有効になる場合があります。\n\nでは、例外を設定したい場合はどうなるでしょうか。たとえば、`internal.example.com`と`internal2.example.com`以外のすべてで、プロキシサーバーを経由したい場合です。このような場合が`no_proxy`変数の出番です。`no_proxy`を次のように定義します。\n\n```sh\nexport no_proxy=internal.example.com,internal2.example.com\n```\n\nでは、IPアドレスを除外したい場合はどうすればよいでしょうか？アスタリスクやワイルドカードは使用できるのでしょうか？CIDRブロック（例:`192.168.1.1/32`）は？\n\nこれらの答えも、「状況によって異なる」です。つまり「使用言語やツールという”PC環境”によって、proxy変数の処理方法が異なる」のが、no proxyがわかりにくいとされている理由です。次の項では、proxy変数の処理方法の違いについてさらに掘り下げます。\n\n### なぜno proxyはこんなに複雑なのか？\n\nこの問題の理解を深めるため、no proxyを巡るこれまでの経緯を説明しておきます。\n\n1994年においてほとんどのウェブクライアントは、[`http_proxy`と`no_proxy`環境変数をサポートするCERNの](https://courses.cs.vt.edu/~cs4244/spring.09/documents/Proxies.pdf)`libwww`を使用していました。`libwww`は、`http_proxy`の小文字形式のみを使用し、[`no_proxy`構文は以下のようにシンプルでした。](https://github.com/w3c/libwww/blob/8678b3dcb4191065ca39caea54bb1beba809a617/Library/src/HTAccess.c#L234-L239)\n\n```\nno_proxy is a comma- or space-separated list of machine\nor domain names, with optional :port part.  If no :port\npart is present, it applies to all ports on that domain.\n\nExample:\n\t\tno_proxy=\"cern.ch,some.domain:8001\"\n```\n\nつまり、元々「小文字表記のみ」で始まったのですが、その後新しいクライアントである`wget`や`curl`の登場により、`no proxy`の大文字が使用可になったり、不可とされたりと変遷しているのです。\n\n1996年1月にHrvoje Niksicが、`libwww`をリンクせずに独自のHTTP実装を追加する新しいクライアント、`geturl`（現在の`wget`の前身）をリリースしました。翌月には`geturl`が[バージョン1.1でhttp\\_proxyのサポートを追加](https://ftp.sunet.se/mirror/archive/ftp.sunet.se/pub/www/utilities/wget/old-versions/)され、同年5月には`geturl`バージョン1.3で`no_proxy`のサポートが追加されました。ここでは`libwww`と同様に、`geturl`では小文字形式`no_proxy`のみのサポートでした。\n\n1998年1月には、Daniel Stenbergが`curl`v5.1をリリースし、[`http_proxy`および`no_proxy`](https://github.com/curl/curl/blob/ae1912cb0d494b48d514d937826c9fe83ec96c4d/CHANGES#L929-L944)変数をサポート。また、大文字の形式の`HTTP_PROXY`および`NO_PROXY`も許可されました。\n\n2009年3月にはcurl v7.19.4がセキュリティ上の懸念から、大文字`HTTP_PROXY`のサポートを廃止します。`curl`では`HTTP_PROXY`は無視されますが、`HTTPS_PROXY`は現在でも動作します。\n\n### 一目でわかるproxy変数の処理方法の違い\n\nGitLabの[Nourdinel Bachaが調査したところ](https://gitlab.com/gitlab-com/support/support-team-meta/-/issues/2991)、これらのプロキシサーバー変数の処理方法は、使用言語やツールによって異なることがわかりました。\n\n#### http_proxyとhttps_proxyの場合\n\n各行はサポートされている動作を表し、各列にはそれが適用されるツール（例：curl）または言語（例：Ruby）を表しています。\n\n|                 | curl      | wget           | Ruby          | Python    | Go        |\n|-----------------|-----------|----------------|---------------|-----------|-----------|\n| `http_proxy`    | はい       | はい            | はい           | はい       | はい       |\n| `HTTP_PROXY`    | いいえ        | いいえ             | はい ([警告](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1519)) | はい (`REQUEST_METHOD` が環境にない場合)       | はい       |\n| `https_proxy`   | はい       | はい            | はい           | はい       | はい       |\n| `HTTPS_PROXY`   | はい       | いいえ             | はい           | はい       | はい       |\n| 大文字と小文字の優先順位 | 小文字 | 小文字のみ | 小文字     | 小文字 | 大文字 |\n| 参照       | [出所](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2250-L2266) | [出所](https://github.com/jay/wget/blob/099d8ee3da3a6eea5635581ae517035165f400a5/src/retr.c#L1222-L1239) | [出所](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1474-L1543) | [出所](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2488-L2517) | [出所](https://github.com/golang/go/blob/682a1d2176b02337460aeede0ff9e49429525195/src/vendor/golang.org/x/net/http/httpproxy/proxy.go#L82-L97) |\n\nこの表から以下のことがわかります。\n\n* http\\_proxyとhttps\\_proxyは常に全面的にサポートされているが、HTTP\\_PROXYは必ずしもサポートされているわけではない。  \n* Python（urllib経由）では状況がさらに複雑となる。HTTP\\_PROXYが使用できるのは、[REQUEST\\_METHODが環境で定義されていない場合に限られる](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2504-L2508)。  \n* Goだけは他と異なり、小文字バージョンより大文字バージョンを優先する。\n\n環境変数はすべて大文字だと思われがちですが、実は最初に登場した`http_proxy`に倣い、小文字表記が事実上のスタンダードとなっています。よくわからない場合は、普遍的にサポートされている小文字形式の使用をおすすめします。\n\n#### no_proxyの場合\n\nさて、次は`no_pproxy`について説明します。次の表は、さまざまな実装の状態を示しています。こちらの表は`http_proxy`の場合に比べてもっと複雑です。例えば、`no_proxy`設定が次の様に定義されているとします。\n\n```sh\nexport no_proxy=example.com\n```\n\nこれはドメインが完全一致である必要があるのか、それともsubdomain.example.comのようなサブドメインも含まれるのでしょうか。次の表は様々な実装状況を示しています。「サフィックス（接尾辞）と一致？」の行を見ると分かるように、実際にはすべての実装がサフィックス（ドメイン末尾）を適切に一致させることができます。\n\n|                       | curl      | wget           | Ruby      | Python    | Go        |\n|-----------------------|-----------|----------------|-----------|-----------|-----------|\n| `no_proxy`            | はい       | はい            | はい       | はい       | はい       |\n| `NO_PROXY`            | はい       | いいえ             | はい       | いいえ       | はい       |\n| 大文字と小文字の優先順位       | 小文字 | 小文字のみ | 小文字 | 小文字のみ | 大文字 |\n| サフィックス（接尾辞）と一致？     | はい       | はい            | はい       | はい       | はい       |\n| `.`でリーディング停止？   | はい       | いいえ             | はい       | はい       | いいえ        |\n| `*` はすべてのホストに一致？| はい       | いいえ             | いいえ        | はい       | はい       |\n| 正規表現をサポート？     | いいえ        | いいえ             | いいえ        | いいえ        | いいえ        |\n| CIDRブロックをサポート？ | いいえ        | いいえ             | はい       | いいえ        | はい       |\n| ループバックIPを検出する？ | いいえ        | いいえ             | いいえ        | いいえ        | はい       |\n| 参考             | [出所](https://github.com/curl/curl/blob/30e7641d7d2eb46c0b67c0c495a0ea7e52333ee2/lib/url.c#L2152-L2206) | [出所](https://github.com/jay/wget/blob/099d8ee3da3a6eea5635581ae517035165f400a5/src/retr.c#L1266-L1274) | [出所](https://github.com/ruby/ruby/blob/0ed71b37fa9af134fdd5a7fd1cebd171eba83541/lib/uri/generic.rb#L1545-L1554) | [出所](https://github.com/python/cpython/blob/030a713183084594659aefd77b76fe30178e23c8/Lib/urllib/request.py#L2519-L2551)| [出所](https://github.com/golang/go/blob/682a1d2176b02337460aeede0ff9e49429525195/src/vendor/golang.org/x/net/http/httpproxy/proxy.go#L170-L206) |\n\nただし、`no_proxy`設定の先頭に「.」がある場合、動作が異なります。\n\nたとえば、`curl`と`wget`は動作が異なります。`curl`は常に先頭の「.」を削除し、ドメインサフィックスと照合します。次の呼び出しはプロキシをバイパスします。\n\n```sh\n$ env https_proxy=http://non.existent/ no_proxy=.gitlab.com curl https://gitlab.com\n\u003Chtml>\u003Cbody>You are being \u003Ca href=\"https://about.gitlab.com/\">redirected\u003C/a>.\u003C/body>\u003C/html>\n```\n\nただし、`wget`は先頭の「`.`」を削除せず、ホスト名に対して正確な文字列一致を実行します。その結果、`wget`はトップレベルドメインが使用されている場合にプロキシの使用を試みます。\n\n```sh\n$ env https_proxy=http://non.existent/ no_proxy=.gitlab.com wget https://gitlab.com\nResolving non.existent (non.existent)... failed: Name or service not known.\nwget: unable to resolve host address 'non.existent'\n```\n\nすべての実装において、正規表現はサポートされません。\n\n正規表現には独自の特徴（PCRE、POSIXなど）があるため、正規表現を使用すると問題がさらに複雑になると思われます。また、正規表現を使用すると、パフォーマンスとセキュリティの問題が発生する可能性があります。\n\n`no_proxy`を`*`に設定するとプロキシが完全に無効になる場合もあるが、これはすべてに共通するルールではない。  \n\nプロキシを使用するかどうかを決定する際に、ホスト名をIPアドレスに解決するためのDNSルックアップを実行する実装はない。\n\nクライアントによってIPアドレスが明示的に使用されることが予想される場合を除き、`no_proxy`変数にIPアドレスを指定しないようにしましょう。\n\n`18.240.0.1/24`などのCIDRブロックは、リクエストが直接IPアドレスに対して行われた場合にのみ機能します。CIDRブロックが許可されるのはGoとRubyのみです。他の実装とは異なり、GoではループバックIPアドレスが検出されると、プロキシの使用が自動的に無効になります。\n\n### GitLabのお客様が抱えたno proxy問題\n\n大文字小文字表記、言語とツールによるリアクションの違いに注意を払う必要があるのは、複数の言語で記述されたアプリケーションを、プロキシサーバーを備えた企業のファイアウォールの背後で動作させる場合です。GitLabもそのひとつであり、RubyとGoで記述された複数のサービスで構成されています。\n\nここでGitLabのあるお客様の例を挙げましょう。お客様はプロキシ構文を次のように設定しました。\n\n```yaml\nHTTP_PROXY: http://proxy.company.com\nHTTPS_PROXY: http://proxy.company.com\nNO_PROXY: .correct-company.com\n```\n\nこのお客様からGitLabに以下の問題の報告がありました。\n\n1. コマンドラインからの`git` pushが起動した\n2. ウェブUI経由で行われたGitの変更が失敗した\n\n連絡を受けたサポートエンジニアは、[Kubernetes](https://about.gitlab.com/ja-jp/blog/what-is-kubernetes/)の構文の問題により、古い値が残っていることを発見しました。ポッドの環境は実際には次のようになっていました。\n\n```yaml\nHTTP_PROXY: http://proxy.company.com\nHTTPS_PROXY: http://proxy.company.com\nNO_PROXY: .correct-company.com\nno_proxy: .wrong-company.com\n```\n\n`no_proxy`と`NO_PROXY`、両者の定義が一致していないため警告が出ました。定義を一致させるか／誤ったエントリを削除することで、この問題を解決できます。\n\nこの古いエントリの何が原因で問題が起きたのか、もう少し詳しく見てみることにします。先ほど「[no proxyの場合](#bookmark=id.3j5kjy3c5qh2)」で述べたことをここで思い出してみましょう。\n\n1. Rubyはまず小文字形式を試す\n2. Goはまず大文字形式を試す\n\nその結果、GitLab WorkhorseなどのGoで記述されたサービスには正しいプロキシ構文となりました。Goサービスが主にこのアクティビティを処理したため、コマンドラインからの`git push`は正常に機能しました。\n\n```mermaid\nsequenceDiagram\n    participant C as Client\n    participant W as Workhorse\n    participant G as Gitaly\n    C->>W: 1. git push\n    W->>G: 2. gRPC: PostReceivePack\n    G->>W: 3. OK\n    W->>C: 4. OK\n```\n\ngRPC呼び出しでは、`no_proxy`がGitalyに直接接続するように適切に構成されていたため、プロキシの使用が試行されませんでした。\n\nただし、ユーザーがUIを変更すると、GitalyはリクエストをRubyで記述された`gitaly-ruby`サービスに転送します。`gitaly-ruby`はリポジトリに変更を加え、[gRPCコールバックを介して親プロセスにレポートを返します](https://gitlab.com/gitlab-org/gitaly/-/issues/3189)(英語）。ただし、以下の手順4に示すように、レポート手順は実行されませんでした。\n\n```mermaid\nsequenceDiagram\n    participant C as Client\n    participant R as Rails\n    participant G as Gitaly\n    participant GR as gitaly-ruby\n    participant P as Proxy\n    C->>R: 1. Change file in UI\n    R->>G: 2. gRPC: UserCommitFiles\n    G->>GR: 3. gRPC: UserCommitFiles\n    GR->>P: 4. CONNECT\n    P->>GR: 5. FAIL\n```\n\ngRPCは基盤となるトランスポートとしてHTTP/2を使用するため、`gitaly-ruby`は間違った`no_proxy`設定で構成されたプロキシへのCONNECTを試行しました。プロキシはこのHTTP要求を即座に拒否し、ウェブUIプッシュケースで失敗を引き起こしました。\n\n環境から小文字の`no_proxy`を削除すると、UIからのプッシュが期待どおりに機能し、`gitaly-ruby`が親のGitalyプロセスに直接接続されました。以下の図のステップ4は適切に機能しました。\n\n```mermaid\nsequenceDiagram\n    participant C as Client\n    participant R as Rails\n    participant G as Gitaly\n    participant GR as gitaly-ruby\n    participant P as Proxy\n    C->>R: 1. Change file in UI\n    R->>G: 2. gRPC: UserCommitFiles\n    G->>GR: 3. gRPC: UserCommitFiles\n    GR->>G: 4. OK\n    G->>R: 5. OK\n    R->>C: 6. OK\n```\n\n#### もう一つの原因はgRPCにあった\n\n`https://`ではなく`http://`が使用されています。セキュリティの観点からは理想的ではありませんが、TLS証明書の検証の問題によりクライアントが失敗するという面倒を避けるために行う場合もあります。\n\nしかしこの場合、HTTPSプロキシが指定されていれば、この問題は発生しなかったでしょう。HTTPSプロキシが使用されている場合、gRPCは[HTTPSプロキシをサポートしていない](https://github.com/grpc/grpc/issues/20939)ため、この設定を無視するからです。\n\n### 解決策：最小限の共通項で設定する\n\n小文字と大文字のプロキシ設定で矛盾した値を定義すべきではないことは、誰もが同意すると思います。ただし、複数の言語で記述されたスタックを管理する必要がある場合は、HTTPプロキシ構文を最も共通する設定で行うよう検討することをおすすめします。\n\n#### `http_proxy` と `https_proxy`\n\n* 小文字形式を使用する。 `HTTP_PROXY` は常にサポートまたは推奨されるわけではない。\n    * どうしても大文字形式も使用する必要がある場合は、__必ず__ 同じ値を共有する。\n\n#### `no_proxy`\n\n1. 小文字形式を使用する。\n2. カンマ区切りの`hostname:port`値を使用する。\n3. IPアドレスは問題ないが、ホスト名は解決されない。\n4. サフィックスは常にマッチングされる(例:`example.com`は`test.example.com`と一致)。\n5. トップレベルドメインを一致させる必要がある場合は、先頭のドット(`.`)を使用しない。\n6. GoとRubyのみがCIDRマッチングをサポートしているため、CIDRマッチングの使用は避ける。\n\n### 解決策：`no_proxy`の標準化チェックリスト\n\n最小公分母を知っておくと、定義が異なるウェブクライアントにコピーされた場合に、問題を回避する上で役立ちます。しかし、`no_proxy`やその他のプロキシ設定には、間に合わせの標準よりも、文書化された標準が必要かもしれません。以下のリストを出発点としてお役立てください。\n\n1. 大文字の変数よりも小文字の変数を優先する (例 `http_proxy` は`HTTP_PROXY`の前に検索すべき)。\n2. カンマ区切りの `hostname:port` 値を使用する。\n    * 各値にはオプションの空白を含めることができる。\n3. DNSルックアップの実行や、正規表現の使用を行わない。\n4. **すべての** ホストに一致させるには`*`を使用する。\n5. 先頭のドット (`.`) を削除し、ドメインサフィックスに対してマッチングさせる。\n6. CIDRブロックマッチングをサポートする。\n7. 特別なIPアドレスを想定しない（たとえば`no_proxy`のループバックアドレス)。\n\n#### まとめ\n\n最初のウェブプロキシがリリースされてから25年以上経ちました。環境変数を介してウェブクライアントを構成する基本的な仕組みはあまり変わっていませんが、さまざまな実装で微妙な違いが生じています。\n\n今回、GitLabのあるお客様の具体的な事例をご紹介しました。このお客様の状況は以下のとおりでした。\n\n* 競合する`no_proxy`変数と`NO_PROXY`変数を誤って定義  \n* RubyとGoはこれらの設定を処理する方法が異なるため、トラブルシューティングに何時間も費やす\n\nこのブログではこの2つの違いに焦点を当て、解説しました。皆様の本番スタックで将来の問題発生回避にお役立ていただけると幸いです。また、設定標準チェックリストを参照して、ウェブクライアントの保守担当者様が動作を標準化し、このような問題を根本的に回避することを願っています。\n\nGitの利便性を生かしつつ、一元化されたプラットフォームでデベロッパー、セキュリティ担当者、運用チームをサポートするGitLabでは、[AIによるコード提案機能があるため、効率性を高められます](https://about.gitlab.com/ja-jp/platform/)。導入検討中の方は、ぜひ無料でのトライアルをお試しください。\n\n> [無料トライアルを開始してみる](https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp/platform&glm_content=default-saas-trial)\n\n画像出展： [PixaBay](https://pixabay.com/illustrations/question-mark-pile-questions-symbol-2492009)\n{: .note}\n\n\u003Cbr>\u003Cbr>\u003Cbr>\n\n*監修：小松原 つかさ  [@tkomatsubara](https://gitlab.com/tkomatsubara)\u003Cbr>\n（GitLab合同会社 ソリューションアーキテクト本部 シニアパートナーソリューションアーキテクト）*",[272,900,901,902],"careers","user stories","startups","2025-03-17",{"slug":905,"featured":6,"template":686},"we-need-to-talk-no-proxy","content:ja-jp:blog:we-need-to-talk-no-proxy.yml","We Need To Talk No Proxy","ja-jp/blog/we-need-to-talk-no-proxy.yml","ja-jp/blog/we-need-to-talk-no-proxy",{"_path":911,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":912,"content":918,"config":925,"_id":927,"_type":16,"title":928,"_source":18,"_file":929,"_stem":930,"_extension":21},"/ja-jp/blog/basics-of-gitlab-ci-updated",{"title":913,"description":914,"ogTitle":913,"ogDescription":914,"noIndex":6,"ogImage":915,"ogUrl":916,"ogSiteName":700,"ogType":701,"canonicalUrls":916,"schema":917},"CI 入門：ジョブを順序どおりに、並列に、または順不同で実行する方法","継続的インテグレーション (CI) 入門：CI は初めてですか？GitLab CI の使い方を学び、最初のCIパイプラインをGitLabでビルドしてみましょう。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662061/Blog/Hero%20Images/cicdcover.png","https://about.gitlab.com/blog/basics-of-gitlab-ci-updated","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"CI 入門：ジョブを順序どおりに、並列に、または順不同で実行する方法\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-12-10\",\n      }",{"title":913,"description":914,"authors":919,"heroImage":915,"date":921,"body":922,"category":14,"tags":923,"updatedDate":924},[920],"Itzik Gan Baruch","2020-12-10","[継続的インテグレーション (CI) (英語版)](https://about.gitlab.com/topics/ci-cd/) のことを何一つ知らず、ソフトウェア開発ライフサイクルに [どうして CI が必要なのか (英語版)](https://about.gitlab.com/blog/how-to-keep-up-with-ci-cd-best-practices/) 分からない、と仮定しましょう。\n\nいま、あるプロジェクトで作業をしていて、そこには2つのテキストファイルから成るコードがあるものとします。さらに、これらの2つのファイルには「Hello world」というフレーズが含まれている必要がある、という点に注意してください。\n\nこのフレーズが含まれていなければ、開発チームがその月のお給料を受け取れないことになるかもしれないくらい、重要なポイントです。\n\nそこで、責任感のあるソフトウェアデベロッパーが、顧客にコードを納品する前に実行する、短いスクリプトを書きました。\n\n以下のような非常に洗練されたコードです。\n\n```bash\ncat file1.txt file2.txt | grep -q \"Hello world\"\n```\n\nここでの懸念事項はチームには10名のデベロッパーがいて、人的要因がコードの品質に大きな影響を及ぼす可能性があるという点です。\n\n1週間前、新しくチームに入ったメンバーがこのスクリプトを実行し忘れ、3件のクライアントに機能しないビルドが納品されるという事態が発生しました。この事態の解決にあたり、幸いにもコードは既にGitLab にあり、[ビルトインの CI](https://about.gitlab.com/ja-jp/solutions/continuous-integration/) があることが分かりました。さらに、あるカンファレンスで、テスト実行にCIを使うのが一般的ということを耳にしていました。\n\n## CI 内で最初のテストを実行する\n\nドキュメントによると、CI の実行に必要なのは `.gitlab-ci.yml` ファイル内に 以下の2 行のコードを追加することだけでした。\n\n```yaml\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n```\n\nコミットして...無事にビルドが成功しました。\n\n![CI内でビルドに成功](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_succeeded.png)\n\nでは、2 つ目のファイルの「world」という文言を「Africa」に置き換え、何が起こるか確認してみましょう。\n\n![CI内でビルドに失敗](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/build_failed.png)\n\nビルドは予想どおり失敗します。\nここで、自動化テストが完成しました。GitLab CI は、DevOps 環境内でソースコードのリポジトリに新しいコードをプッシュするたびにこのテストスクリプトを実行します。\n\n__注:__ 上記例では、file1.txt と file2.txt がGitLabランナーを実行するホストに存在すると仮定しています。\n\nこの例を実際に GitLabで実行するには、以下のようにファイルを作成するコードを実行した後、テストスクリプトを実行する必要があります。\n\n```yaml\ntest:\nbefore_script:\n      - echo \"Hello \" > | tr -d \"\\n\" | > file1.txt\n      - echo \"world\" > file2.txt\nscript: cat file1.txt file2.txt | grep -q 'Hello world'\n```\n\nなお、分かりやすくするために、この 2 つのファイルは既にホストに存在していると仮定し、以降の例では作成しないものとします。\n\n## CIビルド結果をダウンロード可能にする\n\n次にすることは、顧客に納品するコードをパッケージ化することです。ソフトウェア開発プロセスのこの部分も自動化してしまいましょう。\n\nまず、CI に別のジョブを定義する必要があります。このジョブは「package」という名前にしましょう。\n\n```yaml\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > package.gz\n```\n\nよって、今ここにはタブが 2 つあります。\n\n![2つのタブ ― 2つのジョブから生成](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/two_tabs.png)\n\nしかし、新たに作成されるファイルがダウンロードできるようにビルドの「アーティファクト」であることを指定し忘れてしまいました。。修正するには、`artifacts` セクションを追加します。\n\n```yaml\ntest:\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n修正した結果を確認すると、アーティファクトが作成されダウンロードできるようになっています。\n\n![ダウンロードボタンのチェック](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/artifacts.png)\n\nしかし、ここで修正が必要な新たな問題があります。2 つのジョブは現在は並列実行されていますが、テストに失敗した場合、アプリケーションをパッケージ化しないように変更をする必要があります。\n\n## ジョブを順次実行する\n\nそこで「package」ジョブは、テストが成功した場合のみ実行するものとします。`stages` を指定し、ジョブの実行順序を定義しましょう。\n\n```yaml\nstages:\n  - test\n  - package\n\ntest:\n  stage: test\n  script: cat file1.txt file2.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat file1.txt file2.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\n上記のようになりました。\n\nちなみに、コンパイル (我々のケースでは2つのファイルを連結することを意味します) には時間がかかるため、2 回も実行したくはありません。コンパイルは別のステップとして定義しましょう。\n\n```yaml\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npackage:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n```\n\nそれでは、アーティファクトを見てみましょう。\n\n![不必要なアーティファクト](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/clean-artifacts.png)\n\nこの「コンパイル」ファイルを常にダウンロード可能にする必要はないようです。一時的なアーティファクトとして「20 分」で保存期間切れとなるよう、`expire_in` を設定します。\n\n```yaml\ncompile:\n  stage: compile\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n```\n\n構成ファイルは見たところ問題なさそうです。\n\n- アプリケーションをコンパイル、テスト、パッケージ化するために、3 つの連続したステージを作成しました。\n\n- コンパイル済みアプリを次のステージに渡すと、コンパイルを 2回実行する必要がなくなります(それにより実行が高速化されます)。\n\n- パッケージ化されたアプリケーションは、今後も使用できるようビルドアーティファクトとして保管します。\n\n## どのDockerイメージを使用するのか学ぶ\n\nここまでは順調です。しかし、CIビルドにはまだ時間がかかります。ログを見てみましょう。\n\n![ruby3.1](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/ruby-31.png)\n\nここに注目してください。Ruby 3.1とあります。\n\nなぜ Ruby が必要なのかといえば、GitLab.com が [ビルド実行 (英語版)](https://about.gitlab.com/blog/shared-runners/) に Docker イメージを使用しており、[デフォルトで (英語版)](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners)  [`ruby:3.1`](https://hub.docker.com/_/ruby/) イメージを使用するからです。間違いなく、このイメージには必要のないパッケージが多数含まれています。Google で検索して調べたところ、[`alpine`](https://hub.docker.com/_/alpine/) というイメージがあり、ほとんど空の Linux イメージであることが分かりました。\n\nそれでは、`.gitlab-ci.yml` に  `image: alpine` を追加して、このイメージを使用したいと明示的に指定しましょう。\n\nうまくいきました。パイプラインの実行が3 分ほど短縮できたようです。\n\n![ビルド速度を短縮](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/speed.png)\n\nパブリックイメージはたくさんあるようです。\n- [mysql](https://hub.docker.com/_/mysql/)\n- [Python](https://hub.docker.com/_/python/)\n- [Java](https://hub.docker.com/_/java/)\n- [php](https://hub.docker.com/_/php/)\n\nそれにより、我々の技術スタックに適したものを選ぶことができます。不必要なソフトウェアが含まれていないイメージを指定することで、ダウンロード時間が最短で済みます。\n\n## 複雑なシナリオに対応する\n\nさて、ここで新しいクライアントが、アプリを `.gz` ではなく、`.iso` イメージとしてパッケージ化してほしい、と希望しているとします。CI がすべての作業を行なってくれるため、コードにはジョブを 1 つ追加するだけです。ISO イメージはmkisofsコマンドを使用して作成できます。構成ファイルは次のようになります。\n\n```yaml\nimage: alpine\n\nstages:\n  - compile\n  - test\n  - package\n\n# ... \"compile\" and \"test\" jobs are skipped here for the sake of compactness\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\nジョブ名は同じにする必要はありません。ジョブ名が同じだと、ソフトウェア開発プロセスの同じステージでジョブを並列実行できません。そのため、ジョブやステージの名前が同じになるのは、偶然のことだと考えてください。\n\nさて、ビルドは失敗しました。\n\n![mkisofs が欠落しているために失敗したビルド](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/mkisofs.png)\n\n`mkisofs` が `alpine` イメージに含まれていないことが原因です。まずはこのパッケージをインストールする必要があります。\n\n## 欠落しているソフトウェアやパッケージの対応\n\n[Alpine Linux Web サイト (英語版)](https://pkgs.alpinelinux.org/contents?file=mkisofs&path=&name=&branch=edge&repo=&arch=) によると、`mkisofs` は `xorriso`パッケージと `cdrkit` パッケージの一部です。次のコマンドを実行することでパッケージをインストールできます。\n\n```bash\necho \"ipv6\" >> /etc/modules  # enable networking\napk update                   # update packages list\napk add xorriso              # install package\n```\n\nCI ではこれらは他のコマンドと何ら変わりません。`script` セクションで実行する必要があるコマンドの全リストは、このようになります。\n\n```yml\nscript:\n- echo \"ipv6\" >> /etc/modules\n- apk update\n- apk add xorriso\n- mkisofs -o ./packaged.iso ./compiled.txt\n```\n\n構文的に正しくするため、パッケージのインストールに関連したコマンドは `before_script` 内に置きましょう。`before_script` を構成の最上位レベルで使うと、そのコマンドがすべてのジョブの前に実行されることに留意してください。今回は特定のジョブの前で実行させます。\n\n## DAG（有向非巡回グラフ）：より高速で柔軟なパイプラインのために\n\nステージを定義して、テストに合格した場合にのみパッケージジョブを実行するようにしました。後のステージに定義されているジョブに対し、いくつかのジョブのステージ順序を並び替えて先に実行させたい場合はどうすればいいでしょうか。場合によっては、従来のステージ順序がパイプライン全体の実行時間を遅くしてしまう可能性があります。\n\nテストステージに、実行に時間のかかる負荷の高いテストがいくつか含まれており、それらのテストが必ずしもパッケージジョブに関連していないとします。この場合、テストの完了を待たずにパッケージジョブを開始できれば、より効率的になります。それにはDAG (有向非巡回グラフ) が役立ちます。特定のジョブのステージ順序を変えるためには、ジョブの依存関係 (通常のステージの順序をスキップするもの) を定義します。\n\nGitLab には、ジョブ間の依存関係を作成する特殊キーワード `needs` があります。これを使うことで、依存しているジョブが完了するとすぐにジョブを前倒しで実行できるようになります。\n\n次の例では、テストジョブが完了するとすぐにパックジョブが実行を開始します。そのため、将来誰かがテストをテストステージに追加した場合に、新しいテストジョブの完了を待たずにパッケージジョブが実行を開始します。\n\n```yaml\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\n`.gitlab-ci.yml` の最終バージョン:\n\n```yaml\nimage: alpine\n\nstages:\n  - compile\n  - test\n  - package\n\ncompile:\n  stage: compile\n  before_script:\n      - echo \"Hello  \" | tr -d \"\\n\" > file1.txt\n      - echo \"world\" > file2.txt\n  script: cat file1.txt file2.txt > compiled.txt\n  artifacts:\n    paths:\n    - compiled.txt\n    expire_in: 20 minutes\n\ntest:\n  stage: test\n  script: cat compiled.txt | grep -q 'Hello world'\n\npack-gz:\n  stage: package\n  script: cat compiled.txt | gzip > packaged.gz\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.gz\n\npack-iso:\n  stage: package\n  before_script:\n  - echo \"ipv6\" >> /etc/modules\n  - apk update\n  - apk add xorriso\n  script:\n  - mkisofs -o ./packaged.iso ./compiled.txt\n  needs: [\"test\"]\n  artifacts:\n    paths:\n    - packaged.iso\n```\n\nパイプラインが作成できました！ステージは 3 つの連続したステージで、ジョブ `pack-gz` と `pack-iso` が、`package` ステージ内で並列実行されています。\n\n![パイプラインのイラスト](https://about.gitlab.com/images/blogimages/the-basics-of-gitlab-ci/pipeline.png)\n\n## 高度なパイプラインの構築\n\nここからは、高度なパイプラインを構築する方法を説明します。\n\n### CIパイプラインに自動テストを実装 \n\n[DevOps](https://about.gitlab.com/ja-jp/) において、ソフトウェア開発戦略の重要なルールは、素晴らしいユーザーエクスペリエンスを備えた優れたアプリを作成する、というものです。ここでは、CI パイプラインにいくつかのテストを追加し、プロセス全体の早い段階でバグを検出、修正しましょう。この方法なら、問題が大きくなる前や新しいプロジェクトに移る前に問題を修正できます。\n\nGitLabにはさまざまな [テスト](https://docs.gitlab.com/ee/ci/testing/) 用にすぐ使えるテンプレートがあり、これらを使用することで作業が簡単になります。必要な手順は、CI の構成にテンプレートを追加するだけです。\n\nこの例では、[アクセシビリティテスト (英語版)](https://docs.gitlab.com/ee/ci/testing/accessibility_testing.html) を追加します。\n\n```yaml\nstages:\n  - accessibility\n\nvariables:\n  a11y_urls: \"https://about.gitlab.com https://www.example.com\"\n\ninclude:\n  - template: \"Verify/Accessibility.gitlab-ci.yml\"\n```\n\n`a11y_urls` 変数をカスタム化し、Web ページの URL を挿入して、[Pa11y](https://pa11y.org/) と [コード品質](https://docs.gitlab.com/ee/ci/testing/code_quality.html) のテストを行います。\n\n```yaml\n   include:\n   - template: Jobs/Code-Quality.gitlab-ci.yml\n```\n\nGitLab を使うと、マージリクエストのウィジェットエリア内でテストレポートを簡単に確認できます。コードレビュー、パイプラインステータス、テスト結果を一か所にまとめることで、あらゆることがよりスムーズに効率よくできるようになります。\n\n![アクセシビリティレポート](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_10.56.41.png)\n\u003Ccenter>\u003Ci>アクセシビリティ・マージリクエスト・ウィジェット\u003C/i>\u003C/center>\u003Cp>\u003C/p>\n\n![MR 内のコード品質ウィジェット](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.00.25.png)\n\u003Ccenter>\u003Ci>コード品質マージリクエストウィジェット\u003C/i>\u003C/center>\n\n### マトリックスビルド\n\n場合によっては、異なる構成、OS バージョン、プログラミング言語バージョンなどでアプリをテストする必要があります。そのような場合には、[parallel:matrix (英語版)](https://docs.gitlab.com/ee/ci/yaml/#parallelmatrix) ビルドを使って、1 つのジョブ構成でさまざまな組み合わせでアプリケーションを並列にテストします。このブログでは、マトリックスキーワードを使用して、異なるバージョンの Python でコードのテストを行います。\n\n```yaml\npython-req:\n  image: python:$VERSION\n  stage: lint\n  script:\n    - pip install -r requirements_dev.txt\n    - chmod +x ./build_cpp.sh\n    - ./build_cpp.sh\n  parallel:\n    matrix:\n      - VERSION: ['3.8', '3.9', '3.10', '3.11']   # https://hub.docker.com/_/python\n```\n\nパイプライン実行中、このジョブは 4 通りの方法で並列実行されます。それぞれ以下のように異なる Python イメージを使用します。\n\n![実行中のマトリックスジョブ](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-02_at_11.12.48.png)\n\n### ユニットテスト  \n\n#### ユニットテストとは\n\nユニットテストとは、ソフトウェアの個々のコンポーネントや機能が期待通りに機能するかを確認する、対象を絞った単体テストです。ユニットテストは、ソフトウェア開発プロセスの早い段階でバグを検出して修正し、コードのそれぞれの部分が、独立した状態でも正しく機能することを確認するために必須です。\n\n例: 計算機アプリを開発しているとします。加算関数のユニットテストでは、2 + 2 が 4 になるかどうかを確認します。このテストに合格すれば、加算関数が正しく機能していることが確認されます。\n\n#### ユニットテストのベストプラクティス\n\nテストに失敗すると、パイプラインは失敗し、ユーザーに通知が送られます。デベロッパーはジョブのログ (通常何千行もある) を確認し、どこでテストに失敗したのかを特定し、修正します。このチェックには時間がかかり、効率がよくありません。\n\nそこで、[ユニットテストレポート (英語版)](https://docs.gitlab.com/ee/ci/testing/unit_test_reports.html) を使うようにジョブを構成することができます。GitLab はマージリクエストとパイプラインの詳細ページ上にレポートを表示することができるため、ログ全体を確認しなくてもエラーをより簡単に素早く特定できます。\n\n##### JUnitテストレポート\n\n以下はJUnit テストレポートの例です。\n\n![パイプラインの JUnit テストレポート v13 10](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674097/Blog/Content%20Images/pipelines_junit_test_report_v13_10.png){: .shadow.center}\n\n### 統合テストおよびエンドツーエンドテスト戦略\n通常の開発ルーチンに加え、統合テストとエンドツーエンドテスト専用に指定したパイプラインをセットアップすることが非常に重要です。これらのテストでは、[マイクロサービス (英語版)](https://about.gitlab.com/topics/microservices/)、UI テスト、それ他のコンポーネントを含んだ、コードの異なる部位の連携がスムーズかどうかをチェックします。\n\nこれらのテストは [毎晩 (英語版)](https://docs.gitlab.com/ee/ci/pipelines/schedules.html) 実行されます。[テスト結果を自動的に指定のスラックチャンネルに送るよう (英語版)](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#notification-events) に設定することもできます。そうすることで、デベロッパーが翌日出社したときに迅速に問題を確認できます。こうした機能はすべて、問題を早期に特定して修正することを優先すべく設計されています。\n\n### テスト環境 \n\nテストの中には、アプリをしっかりテストするために、テスト環境を構築しなければならない場合があります。GitLab CI/CD を使用するとテスト環境のデプロイが自動化でき、時間を大幅に節約できます。本ブログは主に CI に着目したものとなっているため、詳細には触れません。アプリのデプロイとリリースについては、[GitLab ドキュメントのこのセクション (英語版)](https://docs.gitlab.com/ee/topics/release_your_application.html) を参照してください。\n\n## CI パイプラインへのセキュリティスキャンの実装\n\nCI パイプラインにセキュリティスキャンを実装する方法は次のとおりです。\n\n### SASTおよびDASTインテグレーション\n\nコードの安全性を守ることは非常に重要であり、最新の変更に脆弱性がある場合は、その内容を直ちに把握したいと考えます。したがって、パイプラインにセキュリティスキャンを追加するのが最適な対応といえるでしょう。セキュリティスキャンは、コミットごとにコードをチェックし、リスクがあれば警告してくれます。CI パイプラインに静的アプリケーションセキュリティテスト ([SAST (英語版)](https://docs.gitlab.com/ee/user/application_security/sast/)) や動的アプリケーションセキュリティテスト ([DAST (英語版)](https://docs.gitlab.com/ee/user/application_security/dast/)) などの各種スキャンを追加する方法を説明する以下のナビゲーションをご確認ください。\n\nナビゲーションを開始するには、以下の画像を**クリック**してください。 \n\n[![スキャンの製品ツアー](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.44.42.png)](https://gitlab.navattic.com/gitlab-scans)\n\nさらに、AI を活用すれば、脆弱性をさらに深く掘り下げ、修正方法の提案が得られます。詳しくは以下のナビゲーションをご確認ください。\n\nナビゲーションを開始するには、以下の画像をクリックしてください。\n\n[![製品ツアーでの脆弱性の説明](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749674096/Blog/Content%20Images/Screenshot_2024-04-14_at_13.50.24.png)](https://tech-marketing.gitlab.io/static-demos/pt-explain-vulnerability.html)\n\n## GitLab CI使い方まとめ\n\nまだまだお伝えしたいことはありますが、ここで一度終わりにしましょう。説明に使用した例はすべて意図的に単純なものにしました。これは、慣れない技術スタックの説明が続くことで内容が頭に入らないといった状況を避け、GitLab CIのコンセプトを理解してもらうためです。では、ここまで学んできたことを次にまとめます。\n\n1. GitLab CI に作業をまかせるには、`.gitlab-ci.yml` 内で 1 つ以上の[ジョブ (英語版)](https://docs.gitlab.com/ee/ci/jobs/)を定義する必要があります。\n2. ジョブには名前を付ける必要がありますが、その際は適切な名前を付けるようにしてください。\n3. それぞれのジョブには、指定のキーワードで定義された、 GitLab CI 用の一連のルールと指示が含まれます。\n4. ジョブは、順序どおりに、並列に、または [DAG (英語版)](https://docs.gitlab.com/ee/ci/directed_acyclic_graph/index.html) を使って順不同で実行できます。\n5. ジョブ間ではファイルを渡してビルドアーティファクトに保存し、インターフェイスからダウンロードできるようにすることも可能です。\n6. CI パイプラインに [テストとセキュリティスキャン (英語版)](https://docs.gitlab.com/ee/development/integrations/secure.html) を追加して、開発中のアプリの品質とセキュリティを確保します。\n\n本記事で使用した用語およびキーワードの説明と、関連するドキュメントのリンクを下表にまとめました。\n\n### キーワードの説明とドキュメント\n\n{: #keywords}\n\n| キーワード/用語       | 説明 |\n|---------------|--------------------|\n| [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/) | プロジェクトのビルド方法の定義をすべて含むファイル |\n| [script](https://docs.gitlab.com/ee/ci/yaml/#script)        | 実行するシェルスクリプトを定義する |\n| [before_script](https://docs.gitlab.com/ee/ci/yaml/#before_script) | (全) ジョブの前に実行するコマンドを定義するために使用する |\n| [image](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-image) | 使用するDocker イメージを定義する |\n| [stages](https://docs.gitlab.com/ee/ci/yaml/#stages)         | パイプラインのステージを定義する (デフォルトは test) |\n| [artifacts](https://docs.gitlab.com/ee/ci/yaml/#artifacts)     | ビルドアーティファクトのリストを定義する |\n| [artifacts:expire_in](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in) | 指定時間後にアップロードしたアーティファクトを削除するために使用する |\n| [needs](https://docs.gitlab.com/ee/ci/yaml/#needs) | ジョブ間の依存関係を定義するときに使用し、ジョブを特定の順序で実行することを可能にする |\n| [pipelines](https://about.gitlab.com/topics/ci-cd/cicd-pipeline/) | いくつかのステージ (バッチ) で実行されるビルドのグループを指す |\n\n※ドキュメントはすべて英語版です。\n\n## CI/CDについてさらに詳しく\n\n- [GitLab’s guide to CI/CD for beginners (GitLab のビギナーのための CI/CD ガイド (英語版))](https://about.gitlab.com/blog/beginner-guide-ci-cd/)\n- [Get faster and more flexible pipelines with a Directed Acyclic Graph (有向非巡回グラフ（DAG）を使用して、より高速で柔軟なパイプラインを実現する(英語版))](https://about.gitlab.com/blog/directed-acyclic-graph/)\n- [Decrease build time with custom Docker image (カスタム化した Docker イメージでビルド時間を短縮する (英語版))](http://beenje.github.io/blog/posts/gitlab-ci-and-conda/)\n- [Introducing the GitLab CI/CD Catalog Beta (GitLab CI/CD カタログベータ版の紹介 (英語版))](https://about.gitlab.com/blog/introducing-the-gitlab-ci-cd-catalog-beta/)\n\n## よくある質問 (FAQ)\n\n### CIジョブを順次実行するか、または並列実行するか、どのように選択すればいいですか？\n\nCI ジョブを順次実行するか、並列実行するかを選択する際は、ジョブの依存関係、リソースの利用可能性、実行時間、潜在的な干渉、テストスイートの構造、コスト面を考慮します。たとえば、デプロイジョブが始まるまでに終わらせなければならないビルドジョブがあったとします。その場合、これらのジョブを順次実行して、正しい実行順序を確かめます。一方、ユニットテストや統合テストなどのタスクは独立しており、それぞれの完了には依存しないため、並列実行できます。\n\n### GitLab CIの DAG（有向非巡回グラフ）とは何ですか？また、DAG はパイプラインの柔軟性をどのように向上させますか？\n\nGitLab CI の有向非巡回グラフ (DAG) は、パイプラインステージの順序を並び替えます。DAG はジョブ間の依存関係を設定するため、前のステージにあるジョブが終わり次第、その後のステージのジョブが開始されます。これによりパイプライン全体の実行時間が短縮され、効率が向上し、一部のジョブは通常の順序より早く完了します。\n\n### GitLab の CI ジョブに最適なDockerイメージを選ぶ際に重要視しなければならないことは何ですか？\n\nGitLab はジョブの実行の際に Docker イメージを使用します。デフォルトのイメージは ruby:3.1 です。ジョブの要件によって、最適なイメージを選ぶことがとても大切です。ジョブはまず指定された Docker イメージをダウンロードしますが、イメージに必要ではない追加パッケージが含まれていると、ダウンロードや実行に余分な時間がかかります。そのため、実行時に不必要な遅延が発生しないように、選択したイメージにはジョブに必要なパッケージだけが含まれていることを確認することが重要です。\n\n## 次のステップ\n\nソフトウェア開発プラクティスで後れを取らないためにも、次のステップとしてCI/CDコンポーネントの標準化と再利用方法を理解することをお勧めします。[GitLab CI/CD カタログ (英語版)](https://docs.gitlab.com/ee/architecture/blueprints/ci_pipeline_components/) もご確認ください。\n\n継続的インテグレーションとデリバリー入門は、[こちら](https://about.gitlab.com/ja-jp/solutions/continuous-integration/)をご覧ください。\n\n*監修：川瀬 洋平 [@ykawase](https://gitlab.com/ykawase)\u003Cbr>\n（GitLab合同会社 カスタマーサクセス本部 シニアカスタマーサクセスマネージャー）*",[835,684],"2025-02-20",{"slug":926,"featured":6,"template":686},"basics-of-gitlab-ci-updated","content:ja-jp:blog:basics-of-gitlab-ci-updated.yml","Basics Of Gitlab Ci Updated","ja-jp/blog/basics-of-gitlab-ci-updated.yml","ja-jp/blog/basics-of-gitlab-ci-updated",{"_path":932,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":933,"content":939,"config":945,"_id":947,"_type":16,"title":948,"_source":18,"_file":949,"_stem":950,"_extension":21},"/ja-jp/blog/integrating-azure-devops-scm-and-gitlab",{"title":934,"description":935,"ogTitle":934,"ogDescription":935,"noIndex":6,"ogImage":936,"ogUrl":937,"ogSiteName":700,"ogType":701,"canonicalUrls":937,"schema":938},"Azure DevOpsリポジトリをGitLabと統合する方法","Azure DevOpsリポジトリのGitLabとの統合は簡単。やり方を学んで、Azure DevOpsからGitLab CI/CDへの移行をスムーズに行いましょう。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664363/Blog/Hero%20Images/aleksey-kuprikov.jpg","https://about.gitlab.com/blog/integrating-azure-devops-scm-and-gitlab","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Azure DevOpsリポジトリをGitLabと統合する方法\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Itzik Gan Baruch\"}],\n        \"datePublished\": \"2020-07-09\",\n      }",{"title":934,"description":935,"authors":940,"heroImage":936,"date":941,"body":942,"category":14,"tags":943,"updatedDate":944},[920],"2020-07-09","## 目次\n1. Azure DevOpsはGitLabに統合できるのか \n2. GitLabとAzure DevOpsの違い\n3. GitLabからAzureへの接続方法\n4. 推奨される開発フロー\n5. デプロイのワークフローのデモ動画\n6. 試みる価値のあるソリューション\n7. まとめ\n\nAzure DevOpsリポジトリ内にコードを置いたままで、GitLabのパイプラインでCI/CDを実行する方法をご説明します。リンクは特に断りのない限り、英語版ページへのリンクとなります。ご留意ください。\n\n最近、Azure DevOps/VSTS（Visual Studio Team Services）のソースコード管理（SCM）とGitLabを統合することは可能でしょうかと質問を受けることが続きました。こういった質問をしてきた方は、GitLabのような最新の[CI/CD ソリューション](https://about.gitlab.com/topics/ci-cd/)を検討しているものの、段階移行で一時的に新旧のシステムが共存する間は、コードをAzure DevOps/VSTS内で管理する必要があるようです。\n\n## Azure DevOpsはGitLabに統合できるのか\n\nはい、Azure DevOpsはGitLabに統合できます。\n\nGitLabではGitLab CI/CDをGitLabの組み込みSCMと併せて使用することを推奨していますが、Azure DevOpsのソースコード管理とGitLabとを統合すると、コードをAzure [DevOps](https://about.gitlab.com/ja-jp/topics/devops/)リポジトリに残したままGitLab CI/CDも導入できるため、Azure DevOpsから徐々にGitLabに移行することが可能です。GitLabのセルフマネージドバージョンと、SaaSバージョンのどちらでも統合が可能です。しかし、統合可能なのは、Azure DevOps/VSTSの Gitバージョン管理のみです。TFVC（Team Foundation Version Control）はサポートされていませんのでご注意ください。\n\n### Azure DevOpsとの統合を可能にするGitLabの2つの機能\n\n[外部リポジトリ用GitLab CI/CD](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/) ― GitLab CI/CDは外部リポジトリ（GitHub, Bitbucket Cloud など）のGitサーバーで利用できます。\n\n[リモートリポジトリのミラーリング](https://docs.gitlab.com/ee/user/project/repository/mirror/) ― リポジトリは外部ソースとの間でミラーリングできます。どのリポジトリをソースとして使用するかも選択できます。ミラーリングを行なうと、ブランチ、タグ、コミットなどが自動的に同期されます。\n\n#### DevOps におけるリポジトリとは？\n\nGitLabやAzureのようなツールにおけるコードリポジトリは、あらゆるソースコードを格納するために存在します。こういったリポジトリはDevOpsの「リポ」と呼ばれたり、「ソースリポジトリ」と呼ばれたりします。名前がどうであれ、デベロッパーが高いコード品質を目指して作業するための場所をコードリポジトリが提供することに変わりありません。GitLabは、バージョン管理によるソースコード管理に[Gitベースのリポジトリ（日本語版）](https://about.gitlab.com/ja-jp/solutions/source-code-management/)を使用します。Gitベースのリポジトリを使用したバージョン管理により、GitLabユーザーがコードレビューを行い、開発面での問題を簡単に解決することができるのです。\n\n## GitLabとAzure DevOpsの違い\n\nAzure DevOpsには、開発ライフサイクルを管理するための幅広いサービスがあります。主要機能には、アジャイルプランニングボード、ソースコード管理用のプライベートGitリポ、そしてAzureパイプラインなどがあります。\nDevSecOpsライフサイクル全体に対応した単一プラットフォームとして提供されるGitLabには以下が含まれます。\n- プランニングとコラボレーション\n- ソースコード管理\n- コードレビュー\n- CI/CDパイプライン\n- 継続的なセキュリティスキャンと監視\n- 高度なデプロイ\n- 脆弱性の管理\n\u003Cbr>\n\u003Cbr>\nGitLabは、セキュリティとコンプライアンスを強化しながら、DevSecOpsのライフサイクル全体の管理をサポートしてソフトウェアを迅速かつ効率的に提供します。\n\n## GitLabからAzureへの接続方法\n\nソースコード管理をAzureからGitLabへ完全に移行するには時間がかかる場合があります。ここでは、スムーズな移行のために、GitLabからAzure統合に接続する手順を説明します。\n\n1. 「New Project（新規プロジェクト）」ボタンをクリックして、GitLab内に新規プロジェクトを作成します。 ![新規プロジェクトの作成](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado1.png){: .large.center}\n\n2. 「CI/CD for external repo（外部リポジトリ用 CI/CD）」タブを選択し、Repo by URL（リポジトリのURL）をクリックします。  ![外部リポジトリ用 CI/CD](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado2.png){: .large.center}\n\n3. Azure DevOps 内でリポジトリを開き、「Clone（クローン）」をクリックします。\n  ![クローンURLを入手する](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado3.png){: .large.center}\n\n4. URLをコピーします。お使いのリポジトリがプライベートだった場合、Gitの認証情報を生成する必要があります。「Generate Git Credentials（Git認証情報を生成）」をクリックし、ユーザー名とパスワードをコピーしてください。 ![認証情報](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado4.png){: .large.center}\n\n5. 「Git repository URL（Gitリポジトリの URL）下の欄にURLを貼り付けます。\nプロジェクト名を付けます。\n可視性の表示レベルを設定します。\n「プロジェクトを作成」をクリックします。\nAzure DevOpsリポジトリがプライベートだった場合には、ユーザー名とパスワードを追加します。\n\n__注__:リポジトリは、http://、https:// または git:// でアクセスできなければなりません。http:// または https:// プロトコルを使用する場合は、リポジトリへの正確なURLを指定してください。HTTPリダイレクトは実行されません。\n\n  ![プロジェクトフォームの作成\"](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado5.png){: .large.center}\n\n6. プロジェクトはGitLabと正常にミラーリングされました。これで、ブランチ、タグ、コミットがGitLabと自動的に同期されるようになります。\n\n7. CI/CDパイプラインを構成するオプションは2つあります。\n  ![Auto DevOps 設定](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado6.png){: .shadow.large.center}\n\nAuto DevOpsを使わずにパイプライン構成をご自分で定義したい場合には、お使いのリポジトリのルートディレクトリに [.gitlab-ci.yml](https://docs.gitlab.com/ee/ci/yaml/) ファイルを追加してください。このyamlコードには、[CI/CD定義](https://about.gitlab.com/blog/guide-to-ci-cd-pipelines/) を必ずインクルードしてください。\n\nこのファイルがルートディレクトリにインクルードされると、CI/CDパイプラインが各コミットごとにトリガーされます。.gitlab-ci.yml に不慣れな場合には、.gitlab-ci.yml という名前でファイルを作成し、以下のコードを貼り付けてください。このコードにはビルドステージとテストステージがあり、それぞれに、単一のジョブが含まれます。このジョブは各ステージでコンソールにテキストを表示します。\n\n後でそれぞれのジョブにスクリプトを追加できます。また、ジョブやステージの追加も可能です。より複雑なパイプラインを作成するときは、ゼロから着手するのではなく、[GitLabに付属の](https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates)[パイプラインテンプレートを使用する](https://docs.gitlab.com/ee/ci/yaml/#includetemplate)とよいでしょう。\n\n```\nstages:\n  - build\n  - test \n\nbuild:\n  stage: build\n  script:\n    - echo \"Build job\"\n\ntest:\n  stage: test\n  script:\n    - echo \"Test job\"\n```\n\n以上です。これで準備は済みました。\n\n## 推奨される開発フロー \n\n![開発フローの図](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado_7_2.png){: .shadow.large.center}\n\n1. コード（デベロッパーが選択したIDE）\u003Cbr>\nデベロッパーはお気に入りのIDEを使用してコードを開発し、リポジトリをワークステーションに複製し、ブランチを作成します。\n  ![Visual Studioのコード](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado8.png){: .shadow.large.center}\n\u003Cbr>\n\n2. コミット（GIT）\u003Cbr>\nフィーチャーの開発またはバグ修正が完了したあと、デベロッパーはワークをAzureリポジトリサーバーにプッシュします。  ![Azure DevOpsリポ](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado9.png){: .shadow.large.center}\n\u003Cbr>\n3. ビルド（GitLab）\u003Cbr>\nコミット履歴つきのブランチがGitLabにミラーリングされます。CI/CDパイプラインがトリガーされ、このパイプラインにより、コードがビルドされます。  ![GitLabパイプライングラフ](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado10.png){: .shadow.large.center}\n\n    アーティファクトが作成され、ダウンロードできるようになります。\n  ![アーティファクト](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado11.png){: .shadow.large.center}\n\n    「Auto DevOps」が有効化されていれば、コンテナイメージが作成され、ビルトインのコンテナレジストリにプッシュされます。 \n![GitLabコンテナレジストリ](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado12.png){: .shadow.large.center}\n\n    プロジェクト内でパッケージレジストリが有効化されている場合には、パッケージが指定されたパッケージマネージャに公開されます。 \n![GitLabパッケージレジストリ](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado13.png){: .shadow.large.center}\n\u003Cbr>\n4. テスト (GitLab)\u003Cbr>\nCI パイプラインの一環として、セキュリティスキャン、ライセンススキャン、その他のテストが実行されます。 ![GitLab スキャン](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado14.png){: .shadow.large.center}\n\u003Cbr>\n5. レビューとプルリクエスト (GitLabおよびAzure DevOpsリポジトリ)\u003Cbr>\nGitLabでパイプラインの結果をレビューし、エラーなくパイプラインがパスした場合、かつ、新しい変更により新たな脆弱性が生じていなければ、Azure DevOpsでプルリクエストを作成します。コードレビューが始まったら、デベロッパーはメインにマージする前に、新しい変更を加える必要がある場合があります。各コミットは、 GitLab内でCI/CDパイプラインをトリガーします。 ![Azure DevOpsプルリクエスト](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado15.png){: .shadow.large.center}\n\u003Cbr>\n6. マージ（Azure DevOpsリポジトリとGitLab）\u003Cbr>\nAzure DevOpsのプルリクエストが承認され、ブランチがAzure DevOpsリポジトリのメインブランチにマージされます。\n\nパイプラインの構成により異なりますが、メインブランチへのこのマージは GitLab内のCI/CDパイプラインをトリガーし、マージ結果が検証され、新しいパッケージとコンテナイメージがビルドされ、その後それらがデプロイされます。  ![GitLab CI/CDパイプラインのグラフ](https://about.gitlab.com/images/blogimages/ado_and_gitlab/ado16.png){: .shadow.large.center}\n\u003Cbr>\n## デプロイのワークフローのデモ動画\n\n\u003Ciframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/HfpP2pEmkoM\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen>\u003C/iframe>\n\n## 試みる価値のあるソリューション\n\nGitLabは、トップクラスのソースコード管理（SCM）とCI/CDソリューションを単一のアプリケーションで提供し、多くの [GitLab顧客](https://about.gitlab.com/customers/)がこのパワフルな組み合わせを利用しています。しかし、チームがすぐにリポジトリをGitLab SCMに移行できないという制約があるケースがあることも理解しています。そのような場合のために、一時的に外部リポジトリ用GitLab CI/CDを提供しています。\n\n## まとめ\n\nソースコード管理（SCM）とGitLabのCI/CDソリューションは、簡単に統合ができます。「Azure DevOpsリポジトリをGitLabのCI/CDに統合することも**簡単にできる**ということを納得していただけたでしょうか。GitLabのCI/CDについてもっと詳しくお知りになりたい場合には、[こちらの記事（日本語版）](https://about.gitlab.com/ja-jp/solutions/continuous-integration/)をご覧ください。\n\n### GitLab CI/CDについてさらに詳しく\n\n[フォレスターのレポート:主要なCI/CDツールの比較（英語版）](https://about.gitlab.com/analysts/forrester-cloudci19/)\n\n[AWS Fargateを使用したGitLab CIのオートスケール（英語版）](/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate/)\n\n[お客様事例:ゴールドマン・サックスはビルド頻度を2週間に1回から1日に1000回以上へ改善（日本語版）](https://about.gitlab.com/ja-jp/customers/goldman-sachs/)\n\n\u003Cbr>\n\u003Cbr>\n\u003Cbr>\n\nカバーイメージ出典：[Aleksey Kuprikov](https://unsplash.com/@alekskuprfilmz) on [Unsplash](https://unsplash.com/)\n{: .note}\n\n\u003Cbr>\n\u003Cbr>\n\n*監修：ソリス ジェレズ / Jerez Solis [@jerezs](https://gitlab.com/jerezs)\u003Cbr>\n（GitLab合同会社 ソリューションアーキテクト本部 ソリューションアーキテクト）*\n",[111,752,684],"2025-02-26",{"slug":946,"featured":6,"template":686},"integrating-azure-devops-scm-and-gitlab","content:ja-jp:blog:integrating-azure-devops-scm-and-gitlab.yml","Integrating Azure Devops Scm And Gitlab","ja-jp/blog/integrating-azure-devops-scm-and-gitlab.yml","ja-jp/blog/integrating-azure-devops-scm-and-gitlab",{"_path":952,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":953,"content":959,"config":968,"_id":970,"_type":16,"title":971,"_source":18,"_file":972,"_stem":973,"_extension":21},"/ja-jp/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"title":954,"description":955,"ogTitle":954,"ogDescription":955,"noIndex":6,"ogImage":956,"ogUrl":957,"ogSiteName":700,"ogType":701,"canonicalUrls":957,"schema":958},"GitLabとAnsibleを使ってIaCを作成する方法","Ansible playbookを使ってIaCを作成します。GitLab CIが持つ力を探求してみてください。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665322/Blog/Hero%20Images/gitlab-ansible-cover.png","https://about.gitlab.com/blog/using-ansible-and-gitlab-as-infrastructure-for-code","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"GitLabとAnsibleを使ってIaCを作成する方法\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Brad Downey\"},{\"@type\":\"Person\",\"name\":\"Sara Kassabian\"}],\n        \"datePublished\": \"2019-07-01\",\n      }",{"title":954,"description":955,"authors":960,"heroImage":956,"date":963,"body":964,"category":14,"tags":965,"updatedDate":967},[961,962],"Brad Downey","Sara Kassabian","2019-07-01","IaCとして管理されるAnsible playbookを実行する際に力を発揮する、GitLab CIの機能を探求してみませんか。\n\nGitLab CIは、[IaC](https://about.gitlab.com/ja-jp/topics/gitops/infrastructure-as-code/)や[GitOps](https://about.gitlab.com/ja-jp/solutions/gitops/)など、さまざまな用途に使用できる強力なツールです。GitLabはツールに依存しないプラットフォームですが、AnsibleはIaCを管理するために、開発者によく使用される言語なので、今回はAnsibleを使用していきます。\n\n## Ansibleとは\n\nAnsibleはオープンソースであり、デプロイ、構成、そしてコンピュータシステムの管理を自動的に行なう際に使用し、構成管理ツールに分類されます。開発者やシステム管理者がAnsibleを使用すると、サーバーの構成やアプリケーションのデプロイ、またネットワークデバイスの管理といった、複雑な、繰り返しの多いプロセスを自動化できます。AnsibleはYAMLを使って、playbookとして知られている宣言型のタスク説明を作成します。作成された宣言型のタスク説明は、コマンドを実行するターゲットホストへのSSH接続を通じてAnsibleが行なう、望まれるシステム状態を説明してくれます。\n\n## デモ：GitLab CI と Ansible\n\n[GitLab CI](https://about.gitlab.com/ja-jp/solutions/continuous-integration/)の特に優れている機能のひとつは、ローカルの端末等に依存ライブラリをインストールしなくても [Ansible playbook](https://docs.ansible.com/ansible/latest/cli/ansible-playbook.html)（外部サイト）のコードを編集しデプロイできることです。デモでご紹介するプロジェクトは、セキュリティポリシーに従って毎月すべてのデバイスのSNMP文字列を更新する必要がありますが、これはGitLabがホストする [GitLab.com](https://about.gitlab.com/ja-jp/pricing/)で簡単に行なうことができます。  \n\nまずはじめに、Ansible playbookを開いてください。ここには次の4つのタスクがあります。\n\n* ルーターの情報を収集  \n* バージョンを表示  \n* シリアル番号を表示  \n* SNMPを構成\n\nこのデモでは、SNMPの文字列の構成方法に焦点を当てています。構成は簡単な一連のステップに従うことで完了できます。\n\n## はじめに：イシューボード\n\nGitLabではプロジェクトに関する計画はすべて同じやり方、[イシューの起票](https://handbook.gitlab.com/handbook/marketing/brand-and-product-marketing/product-and-solution-marketing/getting-started/101/#issue)から始まります。そのためGitLabのワークフローの最初のステップでは、[ansible-demoプロジェクト](https://gitlab.com/bdowney/ansible-demo)内のイシューボードを確認します。[ansible-demoイシューボード](https://gitlab.com/bdowney/ansible-demo/-/boards)を見ると、すでに [すべてのルーターのSNMP文字列の変更](https://gitlab.com/bdowney/ansible-demo/issues/4)に関連するイシューがあることがわかります。イシューの中に、SNMP文字列を毎月ローテーションさせ、読み取り専用と読み書き両方の場合には、異なる文字列を使用する必要があることを記述したGitLabセキュリティポリシーのWikiへのリンクがあります。\n\n![Security policies](https://about.gitlab.com/images/blogimages/ansible_screenshots/security_policies_1A.png){: .shadow.medium.center}\nSNMP 文字列用の GitLab セキュリティポリシー\n{: .note.text-center}\n\nGitLabのセキュリティポリシーによると、SNMP文字列を毎月更新する必要があります。  \n\n次に、[2つのルーターのデモ](https://gitlab.com/bdowney/ansible-demo/blob/master/ci-cd-demo/ci.yml)でSNMP文字列を設定するコマンドが、イシューで概説されているGitLabのセキュリティポリシーに従っていることを確認します。\n\n![Ansible SNMP change](https://about.gitlab.com/images/blogimages/ansible_screenshots/ansible_snmp_change_2.png){: .shadow.medium.center}\nSNMP 文字列設定のためのコマンド\n{: .note.text-center}\n\nSNMP文字列を設定するコマンドは、Ansible playbookに記載されています。\n\n次に、イシューに戻り、イシューをご自身にアサインしてください。右サイドバーのラベルを`to-do`から`doing`に切り替えるか、または、イシューボードの列をドラッグして移動することもできます。\n\n## マージリクエストを作成する\n\n次のステップでは、イシューからマージリクエスト (MR) を作成します。「Draft」のフラグがMRに付いていることを再度確認してください。これにより、準備ができていないうちにmasterブランチにマージされてしまうことが防止されます。ここでは、SNMP文字列への変更点が少ないので、ローカルの IDEでソースコードを編集するのではなく、GitLabの [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/) を使います。  \n\n* [CI/CD](https://about.gitlab.com/topics/ci-cd/)デモセクションを開きます。  \n* Ansible playbookに移動します。  \n* SNMPセクションを次のように編集します。\n\n```\n-snmp-server community New-SNMP-DEMO1 RO\n\n-snmp-server community Fun-SNMP-RW-STR RW\n```\n\n*  [イシュー](https://gitlab.com/bdowney/ansible-demo/issues/1)で説明されている[GitLab セキュリティポリシー](https://gitlab.com/bdowney/ansible-demo/wikis/Security-Policies)に従い、ROとRWが異なる文字列として設定されていることに注意してください。\n\n## 変更をコミットする\n\nSNMP文字列がガイドラインに沿って更新されましたので、変更をコミットします。最新のコミットでMRが更新されたことを確認するために、side-by-side比較機能を利用してください。\n\n![Commit changes](https://about.gitlab.com/images/blogimages/ansible_screenshots/side-by-side_3.png){: .shadow.medium.center}\nGitLab Ansible 内でのマージリクエストのサイド・バイ・サイド比較\n{: .note.text-center}\n\n並べて比較できるツールにより、変更内容が一目でわかります。\n\n## マージリクエストの出力\n\n変更内容をコミットすると、GitLab CIパイプラインが自動的に起動されます。ここでは、次のようなタスクが実行されます。\n構文のチェック\nドライラン\nラボ/シミュレーション環境での変更点のテスト\nGitLab CIパイプラインの各ジョブの進捗状況と出力を表示して、SNMPの更新を実行します。\n\n![Job running](https://about.gitlab.com/images/blogimages/ansible_screenshots/job_running_4.png){: .shadow.medium.center}\nGitLabジョブの出力\n{: .note.text-center}\n\nジョブからの出力を確認して、シミュレーション環境でSNMPの更新が確実に行なわれたことを確認します。\nこのすべてのタスクは、マージリクエスト (MR) 内で実行され、記録されます。\n\n![Pipeline](https://about.gitlab.com/images/blogimages/ansible_screenshots/pipeline_5A.png){: .shadow.medium.center}\nGitLab CIパイプライン内のチェックマーク\n{: .note.text-center}\n\n緑色のチェックマークは、GitLab CIパイプラインで各タスクが正常に完了したことを示しています。\n次に、ラボのルーターにログインして、変更内容を確認します。\n\n![routers snmp](https://about.gitlab.com/images/blogimages/ansible_screenshots/routersnmp_6.png){: .shadow.medium.center}\nルーターのSNMP\n{: .note.text-center}\n\n読み取り専用（RO）および読み書き（RW）のSNMP文字列の変更点がルーターに反映されています。\n\n## マージリクエストのレビュー\n\nオプションとして、[マージリクエスト（MR）の承認](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)をアクティブ化することもできます。これにより、変更が本番環境に送られる前に、より多くのユーザーが変更点をレビューできるようになります。\n\n![approvers](https://about.gitlab.com/images/blogimages/ansible_screenshots/approvers_7.png){: .shadow.medium.center}\nGitLabでのSNMP文字列の更新\n{: .note.text-center}\n\nマージリクエスト（MR）は、masterブランチへのマージを行なう前に、別のユーザーに作業内容をレビューしてもらうように設定することができます。\n\n## Masterブランチへのマージ\n\nテストが完了したら、変更点をmasterブランチにマージします。masterブランチには、本番環境コードが格納されています。\n準備ができたら、`Mark`ボタンをクリックし、次に`Merge`をクリックします。\n「Draft」のステータスを解決すると、MRがマージされ、イシューがクローズされます。\nすると、新しいパイプラインが実行され、追加のステップとして playbookを本番環境で実行する、すべてのテストが実行されます。\n「パイプライン」の画面では、その進捗とログが確認できます。このプロセスが完了したら、本番用ルーターにログインし、SNMPセキュリティ文字列が更新されたことを確認します。\n\n## GitLab CIの魔法\n\nこれまで説明してきたさまざまな機能を可能にした魔法は GitLab CIです。GitLab CIパイプラインとは、Ansibleコードをテストしてデプロイするために必要なあらゆることを実行する、一連の連続したタスクを意味します。\n\nGitLab CIは、リポジトリ内に存在する単一のシンプルな [YAML ファイル](https://about.gitlab.com/blog/three-yaml-tips-better-pipelines/)である`.gitlab-ci.yml`で構成されています。\n\nこのデモでは`.gitlab-ci.yml`ファイルが3つのステージで構成されていることがご確認いただけます。\n1. Deploy：Ansibleを使用する AWSに 、２つのルーターのシミュレーションネットワークが作成されます。\n2. Demo：SNMP文字列を変更するplaybook が実行されます。\n3. Destory：２つのルーターのシミュレーションネットワークが破棄されます。\n\nGitLab CIは、ベースイメージで始まります。この場合、必要なすべての Ansibleバイナリと依存ライブラリを含むDockerイメージを使用しています。必要に応じて、それぞれのステージで実行するコマンドと、依存関係を指定します。\n\n![More code](https://about.gitlab.com/images/blogimages/ansible_screenshots/more_code_9A.png){: .shadow.medium.center}\n単純なYAMLファイルには、GitLab CIの3つのフェーズが含まれます。\n{: .note.text-center}\n\n![More Code](https://about.gitlab.com/images/blogimages/ansible_screenshots/more_code_10A.png){: .shadow.medium.center}\nGitLab CIのデモレベル\n{: .note.text-center}\n\nGitLab CIのデモステージを覗いてみましょう。これはAnsible playbookを実行しているものです。\n\n今度はパイプラインを見てみましょう。GitLab CIを使用すれば、コンピュータにAnsibleの依存関係をインストールすることなく構成管理を実装できることがわかります。これは、IaCを実行するために GitLab CIを使用する方法の一例に過ぎません。以下のリンクは、完全版チュートリアルの動画ですので、ぜひご覧ください。\n\n\u003C!-- blank line -->\n\u003Cfigure class=\"video_container\">\n  \u003Ciframe src=\"https://www.youtube.com/embed/M-SgRTKSeOg\" frameborder=\"0\" allowfullscreen=\"true\"> \u003C/iframe>\n\u003C/figure>\n\u003C!-- blank line -->\n\n## FAQ - よくある質問\n\n### Q: Ansibleとは\n\nA: Ansibleとは、ITプロセスの自動化と構成管理を可能にするオープンソースのツールです。アプリケーションのデプロイ、構成管理、オーケストレーション、プロビジョニングなど、コンピュータシステムの管理を自動的に行なう際に使用します。\n\nAnsibleを使用すると、サーバーの構成やアプリケーションのデプロイ、またネットワークデバイスの管理といった、複雑な、繰り返しの多いワークフローのオーケストレーションが可能になります。AnsibleはYAMLを使って、playbookとして知られている宣言型のタスク説明を作成します。作成された宣言型のタスク説明は、コマンドを実行するターゲットホストへのSSH接続を通じてAnsibleが行なう、望まれるシステム状態を説明してくれます。詳しくは[こちら](#heading=h.llxgny6efk4z)をご覧ください。\n\n### Q: Ansible Playbookとは\n\nA: Ansible Playbookはyamlで書かれたタスクのリストファイルのことで、指定したインベントリーやホストのグループに対して自動的に実行されます。ネットワークインフラ、WindowsサーバーなどITインフラに適用するタスクやコンフィグレーションをこのファイルで定義します。Ansibleタスクは、1つまたは複数タスクがplayとしてグループ化され、それぞれのplayが特定のホストやホストグループに対して実行されます。クラウド管理、ユーザー管理、ネットワーク、セキュリティ、構成管理などがAnsible Playbookで管理できます。\n\n### Q: GitLab CIとは\n\nA: GitLab CI（継続的インテグレーション、Continuous Integration）とは、GitLab上でコードの変更が行われた際に自動的にテストやビルドを実行するツールで、サードパーティのツールやライブラリを導入しなくても利用できます。GitLab CIは、すべてのコード変更を共有ソースコードリポジトリのmainブランチに早い段階で頻繁に統合し、コミットやマージ時に各変更を自動的にテストし、自動的にビルドを開始するプラクティスのことです。継続的インテグレーションを行うことで、エラーやセキュリティの問題をより簡単に、開発プロセスのかなり早い段階で特定し、修正することが可能になります。詳しくは[こちら](https://about.gitlab.com/ja-jp/topics/ci-cd/#what-is-continuous-integration-ci)をご覧ください。\n\n### Q: GitLab CIとAnsibleを使用するメリットは何ですか\n\nA: GitLab CIなら、ローカルの端末等に依存ライブラリをインストールしなくてもAnsible playbookのコードを編集しデプロイできます。また、GitLab CIパイプラインは、Ansibleコードをテストしてデプロイするために必要なあらゆることを実行する、一連の連続したタスクです。つまり、GitLabでは、リポジトリの管理とCIおよびAnsible Towerのワークフロー実行が行なえます。加えられた変更の内容、たとえば、いつ、誰がどのファイルに対して変更を行なったのかも自動で記録されるうえ、マージリクエスト(MR)を使えば、理由や目的などのメモも残せるなど、いろいろなメリットがあります。\n\n*\\*監修：伊藤 俊廷 [@toshitakaito](https://gitlab.com/toshitakaito) \n（GitLab合同会社 ソリューションアーキテクト本部 スタッフソリューションアーキテクト）*\n",[966,111],"demo","2024-10-21",{"slug":969,"featured":6,"template":686},"using-ansible-and-gitlab-as-infrastructure-for-code","content:ja-jp:blog:using-ansible-and-gitlab-as-infrastructure-for-code.yml","Using Ansible And Gitlab As Infrastructure For Code","ja-jp/blog/using-ansible-and-gitlab-as-infrastructure-for-code.yml","ja-jp/blog/using-ansible-and-gitlab-as-infrastructure-for-code",{"_path":975,"_dir":249,"_draft":6,"_partial":6,"_locale":7,"seo":976,"content":982,"config":988,"_id":990,"_type":16,"title":991,"_source":18,"_file":992,"_stem":993,"_extension":21},"/ja-jp/blog/keeping-git-commit-history-clean",{"title":977,"description":978,"ogTitle":977,"ogDescription":978,"noIndex":6,"ogImage":979,"ogUrl":980,"ogSiteName":700,"ogType":701,"canonicalUrls":980,"schema":981}," git Commit（コミット）の履歴が重要な理由とその整理方法","git コミット履歴は、煩雑になりがち。gitコミットのメッセージ履歴をクリーンに保ち、変更内容を把握する方法とその重要性をご紹介します。","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659457/Blog/Hero%20Images/keep-git-commit-history-clean.jpg","https://about.gitlab.com/blog/keeping-git-commit-history-clean","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \" git Commit（コミット）の履歴が重要な理由とその整理方法\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kushal Pandya\"}],\n        \"datePublished\": \"2018-06-07\",\n      }",{"title":977,"description":978,"authors":983,"heroImage":979,"date":985,"body":986,"category":14,"tags":987,"updatedDate":837},[984],"Kushal Pandya","2018-06-07","## 目次\n\n- git コミットの履歴が重要な理由\n- 直前のgitコミットメッセージを変更する\n- ２つ以上前のgitコミットの内容を修正する\n- 修正用に作ったgitコマンドは元のコミットと組み合わせて履歴をクリーンに保つ\n- gitコミットのセーフティネット reflogs\n- gitコミットを整理して、未来の開発に備えよう\n\ngitコミットは、リポジトリの重要な要素のひとつであり、コミットメッセージはリポジトリの履歴ログでもあります。プロジェクトやリポジトリがチームメンバーに編集・更新（新機能の追加、バグ修正、アーキテクチャのリファクタリングなど）されていくなかで、コミットメッセージは何がどのように変更されたのかを知るための重要な手掛かりとなります。そのため、コミットメッセージは基本的な変更を、簡潔かつ正確に反映することが求められます。\n\n## git コミットの履歴が重要な理由\n\ngitコミットメッセージは、あなたが触れたコードに残す指紋のようなものです。あなたが今日コミットしたコードには、一年後に同じ変更を見たときにもすぐに理解できるよう、簡潔で正確なメッセージが添えてあるべきです。gitコミットがコンテキストに基づいて分割されていれば、該当のコミットで発生したバグを素早く見つけられ、バグの原因となるコミットを元通りに修正することができます。大規模なプロジェクトで作業していると、常に多数の更新、追加、削除が発生します。そのような場合に、適切なコミットメッセージの記載は不可欠になります。この記事では、gitリポジトリでの作業中に開発者がよく使うgitコミットについて解説していきます。\nこの記事では、git の基本的な知識、ブランチの仕組み、ブランチの未コミットの変更をステージングす方法、変更をコミットする方法について理解していることを前提としています。これらの流れがよくわからないという方は、こちらのGitLabドキュメントもご参照ください。\n\n- [Situation 1: I need to change the most recent commit](#situation-1-i-need-to-change-the-most-recent-commit)\n- [Situation 2: I need to change a specific commit](#situation-2-i-need-to-change-a-specific-commit)\n- [Situation 3: I need to add, remove, or combine commits](#situation-3-i-need-to-add-remove-or-combine-commits)\n- [Situation 4: My commit history doesn't make sense, I need a fresh start!](#situation-4-my-commit-history-doesnt-make-sense-i-need-a-fresh-start)\n\nBut before we dive in, let's quickly go through what a typical development workflow looks like in our hypothetical Ruby application.\n\n**Note:** This article assumes that you are aware about basics of Git, how branches work, how to add uncommitted changes of a branch to stage and how to commit the changes. If you're unsure of these flows, [our documentation](https://docs.gitlab.com/ee/topics/git/index.html) is a great starting point.\n\n## A day in the life\n\nHere, we are working on a small Ruby on Rails project where we need to add a navigation view on the homepage and that involves updating and adding several files. Following is a step by step breakdown of the entire flow:\n\n- You start working on a feature with updating a single file; let's call it `application_controller.rb`\n- This feature requires you to also update a view: `index.html.haml`\n- You added a partial which is used in index page: `_navigation.html.haml`\n- Styles for the page also need to be updated to reflect the partial we added: `styles.css.scss`\n- Feature is now ready with the desired changes, time to also update tests; files to be updated are as follows:\n  - `application_controller_spec.rb`\n  - `navigation_spec.rb`\n- Tests are updated and passing as expected, now time to commit the changes!\n\nSince all the files belong to different territories of the architecture, we commit the changes isolated of each other to ensure that each commit represents a certain context and is made in a certain order. I usually prefer backend -> frontend order where most backend-centric change is committed first, followed by the middle layer and then by frontend-centric changes in the Git list commits.\n\n1.  `application_controller.rb` & `application_controller_spec.rb`; **Add routes for navigation**.\n2.  `_navigation.html.haml` &  `navigation_spec.rb`; **Page Navigation View**.\n3.  `index.html.haml`; **Render navigation partial**.\n4.  `styles.css.scss`; **Add styles for navigation**.\n\nNow that we have our changes committed, we create a merge request with the branch. Once you have merge request open, it typically gets reviewed by your peer before the changes are merged into repo's `master` branch. Now let's learn what different situations we may end up with during code review.\n\n## Situation 1: How to change the most recent Git commit\n\nImagine a case where the reviewer looked at `styles.css.scss` and suggested a change. In such a case, it is very simple to do the change as the stylesheet changes are part of **last** commit on your branch. Here's how we can handle this;\n\n- You directly do the necessary changes to `styles.css.scss` in your current branch.\n- Once you're done with the changes, add these changes to stage; run `git add styles.css.scss`.\n- Once changes are staged, we need to _add_ these changes to our last commit; run `git commit --amend`.\n  -  **Command breakdown**: Here, we're asking the `git commit` command to _amend_ whatever changes are present in stage to the most recent commit.\n- This will open your last commit in your Git-defined text editor which has the commit message **Add styles for navigation**.\n- Since we only updated the CSS declaration, we don't need to alter the commit message. At this point, you can just save and exit the text editor that Git opened for you and your changes will be reflected in the commit.\n\nSince you modified an existing Git commit, these changes are required to be _force pushed_ to your remote repo using `git push --force-with-lease \u003Cremote_name> \u003Cbranch_name>`. This command will override the commit `Add styles for navigation` on remote repo with updated commit that we just made in our local repo.\n\nOne thing to keep in mind while force pushing branches is that if you are working on the same branch with multiple people, force pushing may cause trouble for other users when they try to normally push their changes on a remote branch that has new commits force pushed. Hence, use this feature wisely. You can learn more about Git force push options [here](https://git-scm.com/docs/git-push#git-push---no-force-with-lease).\n\n## Situation 2: How to change a specific Git commit changes\n\nIn the previous situation, the Git commit change was rather simple as we had to modify only our last Git commit, but imagine if reviewer suggested to change something in `_navigation.html.haml`. In this case, it is second commit from the top, so changing it won't be as direct as it was in the first situation. Let's see how we can handle this:\n\nWhenever a commit is made in a branch, it is identified by a unique SHA-1 hash string. Think of it as a unique ID that separates one commit from another. You can view all the previous commits, along with their SHA-1 hashes in a branch by running the `git log` command. With this, you would see an output that looks somewhat as follows and is a list of commits, where the most recent commits are at the top;\n\n```\ncommit aa0a35a867ed2094da60042062e8f3d6000e3952 (HEAD -> add-page-navigation)\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 15:24:02 2018 +0530\n\n    Add styles for navigation\n\ncommit c22a3fa0c5cdc175f2b8232b9704079d27c619d0\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 08:42:52 2018 +0000\n\n    Render navigation partial\n\ncommit 4155df1cdc7be01c98b0773497ff65c22ba1549f\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 08:42:51 2018 +0000\n\n    Page Navigation View\n\ncommit 8d74af102941aa0b51e1a35b8ad731284e4b5a20\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\nDate: Wed May 2 08:12:20 2018 +0000\n\n    Add routes for navigation\n```\n\nThis is where `git rebase` command comes into play. Whenever we wish to edit a specific commit with `git rebase`, we need to first rebase our branch by moving back HEAD to the point right _before_ the commit we wish to edit. In our case, we need to change the commit that reads `Page Navigation View`.\n\n![Commit Log](https://about.gitlab.com/images/blogimages/keeping-git-commit-history-clean/GitRebase.png){: .shadow.center.medium}\n\nHere, notice the hash of commit which is right before the commit we want to modify; copy the hash and perform the following steps:\n\n- Rebase the branch to move to commit before our target commit; run `git rebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20`\n  -  **Git command breakdown**: Here we're running Git's `rebase` command with _interactive_ mode with provided SHA-1 hash as commit to rebase to.\n- This will run rebase command for Git in interactive mode and will open your text editor showing all of your commits that came _after_ the commit you rebased to. It will look somewhat like this:\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\npick aa0a35a867e Add styles for navigation\n\n# Rebase 8d74af10294..aa0a35a867e onto 8d74af10294 (3 commands)\n#\n# Commands:\n# p, pick = use commit\n# r, reword = use commit, but edit the commit message\n# e, edit = use commit, but stop for amending\n# s, squash = use commit, but meld into previous commit\n# f, fixup = like \"squash\", but discard this commit's log message\n# x, exec = run command (the rest of the line) using shell\n# d, drop = remove Git commit\n#\n# These lines can be re-ordered; they are executed from top to bottom.\n#\n# If you remove a line here THAT COMMIT WILL BE LOST.\n#\n# However, if you remove everything, the rebase will be aborted.\n#\n# Note that empty commits are commented out\n```\n\nNotice how each commit has a word `pick` in front of it, and in the contents below, there are all possible keywords we can use. Since we want to _edit_ a commit, we need to change `pick 4155df1cdc7 Page Navigation View` to `edit 4155df1cdc7 Page Navigation View`. Save the changes and exit editor.\n\nNow your branch is rebased to the point in time right before the commit you made which included `_navigation.html.haml`. Open the file and perform desired changes as per the review feedback. Once you're done with the changes, stage them by running `git add _navigation.html.haml`.\n\nSince we have staged the changes, it is time to move branch HEAD back to the commit we originally had (while also including the new changes we added), run `git rebase --continue`, this will open your default editor in the terminal and show you the commit message that we edited during rebase; `Page Navigation View`. You can change this message if you wish, but we would leave it as it is for now, so save and exit the editor. At this point, Git will replay all the commits that followed after the commit you just edited and now branch `HEAD` is back to the top commit we originally had, and it also includes the new changes you made to one of the commits.\n\nSince we again modified a commit that's already present in remote repo, we need force push this branch again using `git push --force-with-lease \u003Cremote_name> \u003Cbranch_name>`.\n\n## Situation 3: How to add, remove, or combine Git commits\n\nA common situation is when you've made several commits just to fix something previously committed. Now let's reduce them as much as we can, combining them with the original commits.\n\nAll you need to do is start the interactive rebase as you would in the other scenarios.\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\npick aa0a35a867e Add styles for navigation\npick 62e858a322 Fix a typo\npick 5c25eb48c8 Ops another fix\npick 7f0718efe9 Fix 2\npick f0ffc19ef7 Argh Another fix!\n```\n\nNow imagine you want to combine all those fixes into `c22a3fa0c5c Render navigation partial`. You just need to:\n\n1. Move the fixes up so that they are right below the commit you want to keep in the end.\n2. Change `pick` to `squash` or `fixup` for each of the fixes.\n\n*Note:* `squash` keeps the git fix commit messages in the description. `fixup` will forget the commit messages of the fixes and keep the original.\n\nYou'll end up with something like this:\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\nfixup 62e858a322 Fix a typo\nfixup 5c25eb48c8 Ops another fix\nfixup 7f0718efe9 Fix 2\nfixup f0ffc19ef7 Argh Another fix!\npick aa0a35a867e Add styles for navigation\n```\n\nSave the changes, exit the editor, and you're done! This is the resulting history:\n\n```\npick 4155df1cdc7 Page Navigation View\npick 96373c0bcf Render navigation partial\npick aa0a35a867e Add styles for navigation\n```\n\nAs before, all you need to do now is `git push --force-with-lease \u003Cremote_name> \u003Cbranch_name>` and the changes are up.\n\nIf you want to remove a Git commit from branch altogether, instead of `squash` or `fixup`, just write `drop` or simply delete that line.\n\n### How to avoid Git commit conflicts\n\nTo avoid conflicts, make sure the commits you're moving up the timeline aren't touching the same files touched by the commits left after them.\n\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\nfixup 62e858a322 Fix a typo                 # this changes styles.css\nfixup 5c25eb48c8 Ops another fix            # this changes image/logo.svg\nfixup 7f0718efe9 Fix 2                      # this changes styles.css\nfixup f0ffc19ef7 Argh Another fix!          # this changes styles.css\npick aa0a35a867e Add styles for navigation  # this changes index.html (no conflict)\n```\n\n### Pro-tip: Quick Git commit `fixup`s\n\nIf you know exactly which commit you want to fixup, when committing you don't have to waste brain cycles thinking of good temporary names for \"Fix 1\", \"Fix 2\", ..., \"Fix 42\".\n\n**Step 1: Meet `--fixup`**\n\nAfter you've staged the changes fixing whatever it is that needs fixing, just Git commit all the changes like this:\n\n```\ngit commit --fixup c22a3fa0c5c\n```\n(Note that this is the hash for the commit `c22a3fa0c5c Render navigation partial`)\n\nThis will generate this commit message: `fixup! Render navigation partial`.\n\n**Step 2: And the sidekick `--autosquash`**\n\nEasy interactive rebase. You can have `git` place the `fixup`s automatically in the right place.\n\n`git rebase -i 4155df1cdc7 --autosquash`\n\nHistory will be shown like so:\n```\npick 4155df1cdc7 Page Navigation View\npick c22a3fa0c5c Render navigation partial\nfixup 62e858a322 Fix a typo\nfixup 5c25eb48c8 Ops another fix\nfixup 7f0718efe9 Fix 2\nfixup f0ffc19ef7 Argh Another fix!\npick aa0a35a867e Add styles for navigation\n```\n\nReady for you to just review and proceed.\n\nIf you're feeling adventurous you can do a non-interactive rebase `git rebase --autosquash`, but only if you like living dangerously, as you'll have no opportunity to review the squashes being made before they're applied.\n\n## Situation 4: My Git commit history doesn't make sense, I need a fresh start!\n\nIf we're working on a large feature, it is common to have several fixup and review-feedback changes that are being committed frequently. Instead of constantly rebasing the branch, we can leave the cleaning up of Git commits until the end of development.\n\nThis is where creating patch files is extremely handy. In fact, patch files were the primary way of sharing code over email while collaborating on large open source projects before Git-based services like GitLab were available to developers. Imagine you have one such branch (eg; `add-page-navigation`) where there are tons of commits that don't convey the underlying changes clearly. Here's how you can create a patch file for all the changes you made in this branch:\n\n- The first step to create the patch file is to make sure that your branch has all the changes present from `master` branch and has no conflicts with the same.\n- You can run `git rebase master` or `git merge master` while you're checked out in `add-page-navigation` branch to get all the changes from `master` on to your branch.\n- Now create the patch file; run `git diff master add-page-navigation > ~/add_page_navigation.patch`.\n  -  **Command breakdown**: Here we're using Git's _diff_ feature, and asking for a diff between `master` branch and `add-page-navigation` branch, and _redirecting_ the output (via `>` symbol) to a file named `add_page_navigation.patch` in our user home directory (typically `~/` in *nix operating systems).\n- You can specify any path you wish to keep this file in and the file name and extension could be anything you want.\n- Once the command is run and you don't see any errors, the patch file is generated.\n- Now checkout `master` branch; run `git checkout master`.\n- Delete the branch `add-page-navigation` from local repo; run `git branch -D add-page-navigation`. Remember, we already have changes of this branch in a created patch file.\n- Now create a new branch with the same name (while `master` is checked out); run `git checkout -b add-page-navigation`.\n- At this point, this is a fresh branch and doesn't have any of your changes.\n- Finally, apply your changes from the patch file; `git apply ~/add_page_navigation.patch`.\n- Here, all of your changes are applied in a branch and they will appear as uncommitted, as if all your modification where done, but none of the modifications were actually committed in the branch.\n- Now you can go ahead and commit individual files or files grouped by area of impact in the order you want with concise commit messages.\n\nAs with previous situations, we basically modified the whole branch, so it is time to force push!\n\n## Git commit history: Conclusion\n\nWhile we have covered most common and basic situations that arise in a day-to-day workflow with Git, rewriting Git history is a vast topic and as you get familiar with above tips, you can learn more advanced concepts around the subject in the [Git Official Documentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History). Happy git'ing!\n\nPhoto by [pan xiaozhen](https://unsplash.com/photos/pj-BrFZ9eAA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/clean?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n{: .note}\n> \n\n\u003Cbr>\u003Cbr>\n*監修：知念 梨果 [@rikachinen](https://gitlab.com/rikachinen)* \u003Cbr>\n*（GitLab合同会社 カスタマーサクセス本部 カスタマーサクセスエンジニア）*",[732,712],{"slug":989,"featured":6,"template":686},"keeping-git-commit-history-clean","content:ja-jp:blog:keeping-git-commit-history-clean.yml","Keeping Git Commit History Clean","ja-jp/blog/keeping-git-commit-history-clean.yml","ja-jp/blog/keeping-git-commit-history-clean",2,[693,719,739,759,778,802,821,844,864],1751548582824]