[{"data":1,"prerenderedAt":2124},["ShallowReactive",2],{"/blog/aws-fargate-codebuild-build-containers-gitlab-runner":3,"navigation-en-us":1340,"banner-en-us":1766,"footer-en-us":1776,"blog-post-authors-en-us-Elliot Rushton":2020,"blog-related-posts-en-us-aws-fargate-codebuild-build-containers-gitlab-runner":2034,"blog-promotions-en-us":2060,"next-steps-en-us":2114},{"id":4,"title":5,"authors":6,"body":8,"category":1318,"date":1319,"description":1320,"extension":1321,"externalUrl":1322,"faq":1322,"featured":1323,"heroImage":1324,"meta":1325,"navigation":409,"path":1326,"seo":1327,"slug":1332,"stem":1333,"tags":1334,"template":1338,"updatedDate":1322,"__hash__":1339},"blogPosts/en-us/blog/aws-fargate-codebuild-build-containers-gitlab-runner.md","How to build containers with the AWS Fargate Custom Executor for GitLab Runner and AWS CodeBuild",[7],"Elliot Rushton",{"type":9,"value":10,"toc":1301},"minimark",[11,27,36,41,49,61,65,68,88,92,148,152,287,291,306,317,358,362,384,498,502,505,510,524,819,823,826,834,840,898,901,936,940,943,946,1101,1123,1129,1138,1142,1145,1149,1190,1198,1202,1205,1266,1283,1297],[12,13,14,15,21,22,26],"p",{},"AWS Fargate does not allow containers to run in privileged mode. This means Docker-in-Docker (DinD), which enables the building and running of container images inside of containers, does not work with the ",[16,17,20],"a",{"href":18,"rel":19},"https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate",[],"AWS Fargate Custom Executor driver for GitLab Runner",". The good news is that users don't have to be blocked by this and may use a cloud-native approach to build containers, effectively leveraging a seamless integration with AWS CodeBuild in the ",[16,23,25],{"href":24},"/topics/ci-cd/","CI/CD pipeline",".",[12,28,29,30,35],{},"We provide in-depth instructions on how to autoscale GitLab CI on AWS Fargate in ",[16,31,34],{"href":32,"rel":33},"https://docs.gitlab.com/runner/configuration/runner_autoscale_aws_fargate/",[],"GitLab Runner's documentation",". In this blog post, we explain how to instrument CI containers and source repositories to trigger AWS CodeBuild and use it to build container images.",[37,38,40],"h2",{"id":39},"architecture-overview","Architecture overview",[12,42,43,48],{},[44,45],"img",{"alt":46,"src":47},"AWS Fargate + CodeBuild: a cloud-native approach to build containers with GitLab Runner","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398024/blog/Content%20Images/build-container-image-runner-fargate-codebuild.png","\nHow distinct CI workloads run on Fargate.",[12,50,51,52,56,57,60],{},"The picture above illustrates distinct GitLab CI workloads running on Fargate. The container identified by ",[53,54,55],"code",{},"ci-coordinator (001)"," is running a typical CI job which does not build containers, so it does not require additional configuration or dependencies. The second container, ",[53,58,59],{},"ci-coordinator (002)",", illustrates the problem to be tackled in this post: The CI container includes the AWS CLI in order to send content to an Amazon S3 Bucket, trigger the AWS CodeBuild job, and fetch logs.",[37,62,64],{"id":63},"prerequisites","Prerequisites",[12,66,67],{},"Once these prerequisites are configured, you can dive into the six-step process to configure CI containers and source repositories to trigger AWS CodeBuild and use it to build container images.",[69,70,71,79,82,85],"ul",{},[72,73,74,75,78],"li",{},"The ",[16,76,20],{"href":18,"rel":77},[]," must be set-up appropriately.",[72,80,81],{},"Ensure the AWS IAM user permissions include the ability to create and configure S3 and CodeBuild resources.",[72,83,84],{},"AWS IAM user or service role with permissions to upload files to S3, start CodeBuild jobs, and read CloudWatch Logs.",[72,86,87],{},"AWS IAM user with permissions to create and configure IAM Policies and Users.",[37,89,91],{"id":90},"step-1-create-an-aws-s3-bucket","Step 1: Create an AWS S3 bucket",[93,94,95,104,110,116,123,128,131,136,143],"ol",{},[72,96,97,98,103],{},"In the top menu of ",[16,99,102],{"href":100,"rel":101},"https://aws.amazon.com/console/",[],"AWS Management Console"," click Services.",[72,105,106,107,26],{},"In the Storage section, select ",[53,108,109],{},"S3",[72,111,112,113,26],{},"Click ",[53,114,115],{},"Create bucket",[72,117,118,119,122],{},"Choose a descriptive name (",[53,120,121],{},"ci-container-build-bucket"," will be used as example) and select your preferred region.",[72,124,125,126,26],{},"Leave all other fields with default values and click ",[53,127,115],{},[72,129,130],{},"In the Buckets list, click the name of the bucket you created.",[72,132,112,133,26],{},[53,134,135],{},"Create folder",[72,137,138,139,142],{},"Give it the ",[53,140,141],{},"gitlab-runner-builds"," name.",[72,144,112,145,26],{},[53,146,147],{},"Save",[37,149,151],{"id":150},"step-2-create-an-aws-codebuild-project","Step 2: Create an AWS CodeBuild Project",[93,153,154,161,168,173,183,192,201,207,216,223,232,240,248,256,263,276,284],{},[72,155,156,157,160],{},"Using the AWS Console, click ",[53,158,159],{},"Services"," in the top menu",[72,162,163,164,167],{},"Select ",[53,165,166],{},"CodeBuild"," in the Developer Tools section",[72,169,112,170],{},[53,171,172],{},"Create build project",[72,174,175,176,179,180],{},"In ",[53,177,178],{},"Project Name"," enter ",[53,181,182],{},"ci-container-build-project",[72,184,175,185,188,189],{},[53,186,187],{},"Source provider"," select ",[53,190,191],{},"Amazon S3",[72,193,175,194,197,198,200],{},[53,195,196],{},"Bucket"," select the ",[53,199,121],{}," created in step one",[72,202,203,204],{},"In S3 object key or S3 folder enter ",[53,205,206],{},"gitlab-runner-builds/build.zip",[72,208,175,209,212,213],{},[53,210,211],{},"Environment image",", select ",[53,214,215],{},"Managed image",[72,217,218,219,222],{},"For ",[53,220,221],{},"Operating system"," select your preferred OS from the available options",[72,224,218,225,228,229,26],{},[53,226,227],{},"Runtime(s)",", choose ",[53,230,231],{},"Standard",[72,233,218,234,212,237],{},[53,235,236],{},"Image",[53,238,239],{},"aws/codebuild/standard:4.0",[72,241,218,242,212,245],{},[53,243,244],{},"Image version",[53,246,247],{},"Always use the latest image for this runtime version",[72,249,218,250,188,253],{},[53,251,252],{},"Environment type",[53,254,255],{},"Linux",[72,257,258,259,262],{},"Check the ",[53,260,261],{},"Privileged"," flag",[72,264,265,266,188,269,272,273],{},"For the ",[53,267,268],{},"Service role",[53,270,271],{},"New service role"," and note the sugggested ",[53,274,275],{},"Role name",[72,277,218,278,188,281],{},[53,279,280],{},"Build specifications",[53,282,283],{},"Use a buildspec file",[72,285,286],{},"Scroll down to the bottom of the page and click \"Create build project\"",[37,288,290],{"id":289},"step-3-build-the-ci-container-image","Step 3: Build the CI container image",[12,292,293,294,299,300,305],{},"As stated in Autoscaling GitLab CI on AWS Fargate, a ",[16,295,298],{"href":296,"rel":297},"https://docs.gitlab.com/runner/configuration/runner_autoscale_aws_fargate/#step-1-prepare-a-base-container-image-for-the-aws-fargate-task",[],"custom container is required"," to run GitLab CI jobs on Fargate. Since the solution relies on communicating with S3 and CodeBuild, you'll need to ",[16,301,304],{"href":302,"rel":303},"https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html",[],"have the AWS CLI tool"," available in the CI container.",[12,307,308,309,312,313,316],{},"Install the ",[53,310,311],{},"zip"," tool to make S3 communication smoother. As an example of a Ubuntu-based container, the lines below must be added to the CI container's ",[53,314,315],{},"Dockerfile",":",[318,319,324],"pre",{"className":320,"code":321,"language":322,"meta":323,"style":323},"language-dockerfile shiki shiki-themes github-light","RUN apt-get update -qq -y \\\n    && apt-get install -qq -y curl unzip zip \\\n    && curl -Lo awscliv2.zip https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip \\\n    && unzip awscliv2.zip \\\n    && ./aws/install\n\n","dockerfile","",[53,325,326,334,340,346,352],{"__ignoreMap":323},[327,328,331],"span",{"class":329,"line":330},"line",1,[327,332,333],{},"RUN apt-get update -qq -y \\\n",[327,335,337],{"class":329,"line":336},2,[327,338,339],{},"    && apt-get install -qq -y curl unzip zip \\\n",[327,341,343],{"class":329,"line":342},3,[327,344,345],{},"    && curl -Lo awscliv2.zip https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip \\\n",[327,347,349],{"class":329,"line":348},4,[327,350,351],{},"    && unzip awscliv2.zip \\\n",[327,353,355],{"class":329,"line":354},5,[327,356,357],{},"    && ./aws/install\n",[37,359,361],{"id":360},"step-4-add-codebuild-configuration-to-the-repository","Step 4: Add CodeBuild configuration to the repository",[12,363,364,365,368,369,383],{},"By default, CodeBuild looks for a file named ",[53,366,367],{},"buildspec.yml"," in the build source. This file will instruct CodeBuild on how to build and publish the resulting container image. Create this file with the content below and commit it to the git repository (",[370,371,372,373,377,378,382],"em",{},"if you changed the ",[374,375,376],"strong",{},"Buildspec name"," when configuring the CodeBuild project ",[16,379,381],{"href":380},"#buildspec","in Step 2",", please create the file accordingly","):",[318,385,389],{"className":386,"code":387,"language":388,"meta":323,"style":323},"language-yaml shiki shiki-themes github-light","version: 0.2\n\nphases:\n  install:\n    commands:\n      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&\n      - timeout 15 sh -c \"until docker info; do echo .; sleep 1; done\"\n  build:\n    commands:\n      - echo Build started on `date`\n      - docker -v\n      - docker build -t \u003CIMAGE-TAG> .\n      - echo Build completed on `date`\n\n","yaml",[53,390,391,405,411,419,426,433,443,451,459,466,474,482,490],{"__ignoreMap":323},[327,392,393,397,401],{"class":329,"line":330},[327,394,396],{"class":395},"shJU0","version",[327,398,400],{"class":399},"sgsFI",": ",[327,402,404],{"class":403},"sYu0t","0.2\n",[327,406,407],{"class":329,"line":336},[327,408,410],{"emptyLinePlaceholder":409},true,"\n",[327,412,413,416],{"class":329,"line":342},[327,414,415],{"class":395},"phases",[327,417,418],{"class":399},":\n",[327,420,421,424],{"class":329,"line":348},[327,422,423],{"class":395},"  install",[327,425,418],{"class":399},[327,427,428,431],{"class":329,"line":354},[327,429,430],{"class":395},"    commands",[327,432,418],{"class":399},[327,434,436,439],{"class":329,"line":435},6,[327,437,438],{"class":399},"      - ",[327,440,442],{"class":441},"sYBdl","nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2&\n",[327,444,446,448],{"class":329,"line":445},7,[327,447,438],{"class":399},[327,449,450],{"class":441},"timeout 15 sh -c \"until docker info; do echo .; sleep 1; done\"\n",[327,452,454,457],{"class":329,"line":453},8,[327,455,456],{"class":395},"  build",[327,458,418],{"class":399},[327,460,462,464],{"class":329,"line":461},9,[327,463,430],{"class":395},[327,465,418],{"class":399},[327,467,469,471],{"class":329,"line":468},10,[327,470,438],{"class":399},[327,472,473],{"class":441},"echo Build started on `date`\n",[327,475,477,479],{"class":329,"line":476},11,[327,478,438],{"class":399},[327,480,481],{"class":441},"docker -v\n",[327,483,485,487],{"class":329,"line":484},12,[327,486,438],{"class":399},[327,488,489],{"class":441},"docker build -t \u003CIMAGE-TAG> .\n",[327,491,493,495],{"class":329,"line":492},13,[327,494,438],{"class":399},[327,496,497],{"class":441},"echo Build completed on `date`\n",[37,499,501],{"id":500},"step-5-set-up-the-gitlab-ci-job","Step 5: Set up the GitLab CI job",[12,503,504],{},"Now we will set up the GitLab CI job that will pull everything together.",[506,507,509],"h3",{"id":508},"interacting-with-codebuild-through-the-aws-cli","Interacting with CodeBuild through the AWS CLI",[12,511,512,513,516,517,520,521,316],{},"The CI job will need to interact with AWS Cloud to start CodeBuild jobs, poll the status of the jobs, and fetch logs. Commands such as ",[53,514,515],{},"aws codebuild"," and ",[53,518,519],{},"aws logs"," help to tackle this, so let's use them in a script, ",[53,522,523],{},"codebuild.sh",[318,525,529],{"className":526,"code":527,"language":528,"meta":323,"style":323},"language-bash shiki shiki-themes github-light","#!/bin/bash\n\nbuild_project=ci-container-build-project\nbuild_id=$(aws codebuild start-build --project-name $build_project --query 'build.id' --output text)\nbuild_status=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].buildStatus' --output text)\n\nwhile [ $build_status == \"IN_PROGRESS\" ]\ndo\n    sleep 10\n    build_status=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].buildStatus' --output text)\ndone\n\nstream_name=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].logs.streamName' --output text)\ngroup_name=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[].logs.groupName' --output text)\n\naws logs get-log-events --log-stream-name $stream_name --log-group-name $group_name --query 'events[].message' --output text\necho Codebuild completed with status $build_status\n","bash",[53,530,531,537,541,553,594,627,631,648,653,661,690,695,699,729,760,765,798],{"__ignoreMap":323},[327,532,533],{"class":329,"line":330},[327,534,536],{"class":535},"sAwPA","#!/bin/bash\n",[327,538,539],{"class":329,"line":336},[327,540,410],{"emptyLinePlaceholder":409},[327,542,543,546,550],{"class":329,"line":342},[327,544,545],{"class":399},"build_project",[327,547,549],{"class":548},"sD7c4","=",[327,551,552],{"class":441},"ci-container-build-project\n",[327,554,555,558,560,563,567,570,573,576,579,582,585,588,591],{"class":329,"line":348},[327,556,557],{"class":399},"build_id",[327,559,549],{"class":548},[327,561,562],{"class":399},"$(",[327,564,566],{"class":565},"s7eDp","aws",[327,568,569],{"class":441}," codebuild",[327,571,572],{"class":441}," start-build",[327,574,575],{"class":403}," --project-name",[327,577,578],{"class":399}," $build_project ",[327,580,581],{"class":403},"--query",[327,583,584],{"class":441}," 'build.id'",[327,586,587],{"class":403}," --output",[327,589,590],{"class":441}," text",[327,592,593],{"class":399},")\n",[327,595,596,599,601,603,605,607,610,613,616,618,621,623,625],{"class":329,"line":354},[327,597,598],{"class":399},"build_status",[327,600,549],{"class":548},[327,602,562],{"class":399},[327,604,566],{"class":565},[327,606,569],{"class":441},[327,608,609],{"class":441}," batch-get-builds",[327,611,612],{"class":403}," --ids",[327,614,615],{"class":399}," $build_id ",[327,617,581],{"class":403},[327,619,620],{"class":441}," 'builds[].buildStatus'",[327,622,587],{"class":403},[327,624,590],{"class":441},[327,626,593],{"class":399},[327,628,629],{"class":329,"line":435},[327,630,410],{"emptyLinePlaceholder":409},[327,632,633,636,639,642,645],{"class":329,"line":445},[327,634,635],{"class":548},"while",[327,637,638],{"class":399}," [ $build_status ",[327,640,641],{"class":548},"==",[327,643,644],{"class":441}," \"IN_PROGRESS\"",[327,646,647],{"class":399}," ]\n",[327,649,650],{"class":329,"line":453},[327,651,652],{"class":548},"do\n",[327,654,655,658],{"class":329,"line":461},[327,656,657],{"class":565},"    sleep",[327,659,660],{"class":403}," 10\n",[327,662,663,666,668,670,672,674,676,678,680,682,684,686,688],{"class":329,"line":468},[327,664,665],{"class":399},"    build_status",[327,667,549],{"class":548},[327,669,562],{"class":399},[327,671,566],{"class":565},[327,673,569],{"class":441},[327,675,609],{"class":441},[327,677,612],{"class":403},[327,679,615],{"class":399},[327,681,581],{"class":403},[327,683,620],{"class":441},[327,685,587],{"class":403},[327,687,590],{"class":441},[327,689,593],{"class":399},[327,691,692],{"class":329,"line":476},[327,693,694],{"class":548},"done\n",[327,696,697],{"class":329,"line":484},[327,698,410],{"emptyLinePlaceholder":409},[327,700,701,704,706,708,710,712,714,716,718,720,723,725,727],{"class":329,"line":492},[327,702,703],{"class":399},"stream_name",[327,705,549],{"class":548},[327,707,562],{"class":399},[327,709,566],{"class":565},[327,711,569],{"class":441},[327,713,609],{"class":441},[327,715,612],{"class":403},[327,717,615],{"class":399},[327,719,581],{"class":403},[327,721,722],{"class":441}," 'builds[].logs.streamName'",[327,724,587],{"class":403},[327,726,590],{"class":441},[327,728,593],{"class":399},[327,730,732,735,737,739,741,743,745,747,749,751,754,756,758],{"class":329,"line":731},14,[327,733,734],{"class":399},"group_name",[327,736,549],{"class":548},[327,738,562],{"class":399},[327,740,566],{"class":565},[327,742,569],{"class":441},[327,744,609],{"class":441},[327,746,612],{"class":403},[327,748,615],{"class":399},[327,750,581],{"class":403},[327,752,753],{"class":441}," 'builds[].logs.groupName'",[327,755,587],{"class":403},[327,757,590],{"class":441},[327,759,593],{"class":399},[327,761,763],{"class":329,"line":762},15,[327,764,410],{"emptyLinePlaceholder":409},[327,766,768,770,773,776,779,782,785,788,790,793,795],{"class":329,"line":767},16,[327,769,566],{"class":565},[327,771,772],{"class":441}," logs",[327,774,775],{"class":441}," get-log-events",[327,777,778],{"class":403}," --log-stream-name",[327,780,781],{"class":399}," $stream_name ",[327,783,784],{"class":403},"--log-group-name",[327,786,787],{"class":399}," $group_name ",[327,789,581],{"class":403},[327,791,792],{"class":441}," 'events[].message'",[327,794,587],{"class":403},[327,796,797],{"class":441}," text\n",[327,799,801,804,807,810,813,816],{"class":329,"line":800},17,[327,802,803],{"class":403},"echo",[327,805,806],{"class":441}," Codebuild",[327,808,809],{"class":441}," completed",[327,811,812],{"class":441}," with",[327,814,815],{"class":441}," status",[327,817,818],{"class":399}," $build_status\n",[506,820,822],{"id":821},"add-a-job-to-build-the-resulting-container","Add a job to build the resulting container",[12,824,825],{},"Once the steps one through five are complete, the source repository will be structured as follows:",[318,827,832],{"className":828,"code":830,"language":831,"meta":323},[829],"language-text","/sample-repository\n  ├── .gitlab-ci.yml\n  ├── buildspec.yml\n  ├── codebuild.sh\n  ├── Dockerfile\n  ├── \u003CAPPLICATION-FILES>\n\n","text",[53,833,830],{"__ignoreMap":323},[12,835,836,837,316],{},"The final step to build the container is to add a job to ",[53,838,839],{},".gitlab-ci.yml",[318,841,843],{"className":386,"code":842,"language":388,"meta":323,"style":323},"dockerbuild:\n  stage: deploy\n  script:\n    - zip build.zip buildspec.yml Dockerfile \u003CAPPLICATION-FILES>\n    - aws configure set default.region \u003CREGION>\n    - aws s3 cp build.zip s3://ci-container-build-bucket/gitlab-runner-builds/build.zip\n    - bash codebuild.sh\n\n",[53,844,845,852,862,869,877,884,891],{"__ignoreMap":323},[327,846,847,850],{"class":329,"line":330},[327,848,849],{"class":395},"dockerbuild",[327,851,418],{"class":399},[327,853,854,857,859],{"class":329,"line":336},[327,855,856],{"class":395},"  stage",[327,858,400],{"class":399},[327,860,861],{"class":441},"deploy\n",[327,863,864,867],{"class":329,"line":342},[327,865,866],{"class":395},"  script",[327,868,418],{"class":399},[327,870,871,874],{"class":329,"line":348},[327,872,873],{"class":399},"    - ",[327,875,876],{"class":441},"zip build.zip buildspec.yml Dockerfile \u003CAPPLICATION-FILES>\n",[327,878,879,881],{"class":329,"line":354},[327,880,873],{"class":399},[327,882,883],{"class":441},"aws configure set default.region \u003CREGION>\n",[327,885,886,888],{"class":329,"line":435},[327,887,873],{"class":399},[327,889,890],{"class":441},"aws s3 cp build.zip s3://ci-container-build-bucket/gitlab-runner-builds/build.zip\n",[327,892,893,895],{"class":329,"line":445},[327,894,873],{"class":399},[327,896,897],{"class":441},"bash codebuild.sh\n",[12,899,900],{},"Below are some definitions from terms in the script:",[69,902,903,919,930],{},[72,904,905,908,909,911,912,516,915,918],{},[53,906,907],{},"\u003CAPPLICATION-FILES>"," is a placeholder for the files that will be required to successfully build the resulting container image using the ",[53,910,315],{},", e.g., ",[53,913,914],{},"package.json",[53,916,917],{},"app.js"," in a Node.js application",[72,920,921,923,924],{},[53,922,315],{}," is used to build the resulting image. ",[370,925,926,927],{},"Note: It is not the same file used to build the CI container image, mentioned in ",[16,928,290],{"href":929},"#step-3-build-the-ci-container-image",[72,931,932,933,935],{},"Zip and AWS CLI must be installed in the CI container to make the script work – refer to ",[16,934,290],{"href":929}," for details",[37,937,939],{"id":938},"step-6-set-up-aws-credentials","Step 6: Set up AWS credentials",[12,941,942],{},"The final step is to set up the AWS credentials. As we already mentioned, the CI job will interact with AWS through the AWS CLI to perform a number of operations, and to do that, the AWS CLI needs to authenticate as an IAM user with the permissions listed below. We recommend you create a new user and grant it minimal privileges instead of using your personal AWS user account. For the sake of simplicity, we suggest this approach to complete this walk-through guide.",[12,944,945],{},"This AWS user only needs programmatic access and do not forget to make note of its Access key ID and Secret access key – they will be needed later. A simple way to grant only the minimal privileges for the new user is to create a customer managed policy since it can be directly attached to the user. A group might also be used to grant the same privileges for more users, but it is not mandatory for running the sample workflow.",[69,947,948,1002,1055],{},[72,949,109,950],{},[318,951,955],{"className":952,"code":953,"language":954,"meta":323,"style":323},"language-json shiki shiki-themes github-light","{\n  \"Effect\": \"Allow\",\n  \"Action\": \"s3:PutObject\",\n  \"Resource\": \"arn:aws:s3:::ci-container-build-bucket/gitlab-runner-builds/*\"\n}\n","json",[53,956,957,962,975,987,997],{"__ignoreMap":323},[327,958,959],{"class":329,"line":330},[327,960,961],{"class":399},"{\n",[327,963,964,967,969,972],{"class":329,"line":336},[327,965,966],{"class":403},"  \"Effect\"",[327,968,400],{"class":399},[327,970,971],{"class":441},"\"Allow\"",[327,973,974],{"class":399},",\n",[327,976,977,980,982,985],{"class":329,"line":342},[327,978,979],{"class":403},"  \"Action\"",[327,981,400],{"class":399},[327,983,984],{"class":441},"\"s3:PutObject\"",[327,986,974],{"class":399},[327,988,989,992,994],{"class":329,"line":348},[327,990,991],{"class":403},"  \"Resource\"",[327,993,400],{"class":399},[327,995,996],{"class":441},"\"arn:aws:s3:::ci-container-build-bucket/gitlab-runner-builds/*\"\n",[327,998,999],{"class":329,"line":354},[327,1000,1001],{"class":399},"}\n",[72,1003,166,1004],{},[318,1005,1007],{"className":952,"code":1006,"language":954,"meta":323,"style":323},"{\n  \"Effect\": \"Allow\",\n  \"Action\": [\"codebuild:StartBuild\", \"codebuild:BatchGetBuilds\"],\n  \"Resource\": \"arn:aws:codebuild:\u003CREGION>:\u003CACCOUNT-ID>:project/ci-container-build-project\"\n}\n",[53,1008,1009,1013,1023,1042,1051],{"__ignoreMap":323},[327,1010,1011],{"class":329,"line":330},[327,1012,961],{"class":399},[327,1014,1015,1017,1019,1021],{"class":329,"line":336},[327,1016,966],{"class":403},[327,1018,400],{"class":399},[327,1020,971],{"class":441},[327,1022,974],{"class":399},[327,1024,1025,1027,1030,1033,1036,1039],{"class":329,"line":342},[327,1026,979],{"class":403},[327,1028,1029],{"class":399},": [",[327,1031,1032],{"class":441},"\"codebuild:StartBuild\"",[327,1034,1035],{"class":399},", ",[327,1037,1038],{"class":441},"\"codebuild:BatchGetBuilds\"",[327,1040,1041],{"class":399},"],\n",[327,1043,1044,1046,1048],{"class":329,"line":348},[327,1045,991],{"class":403},[327,1047,400],{"class":399},[327,1049,1050],{"class":441},"\"arn:aws:codebuild:\u003CREGION>:\u003CACCOUNT-ID>:project/ci-container-build-project\"\n",[327,1052,1053],{"class":329,"line":354},[327,1054,1001],{"class":399},[72,1056,1057,1058],{},"CloudWatch Logs",[318,1059,1061],{"className":952,"code":1060,"language":954,"meta":323,"style":323},"{\n  \"Effect\": \"Allow\",\n  \"Action\": \"logs:GetLogEvents\",\n  \"Resource\": \"arn:aws:logs:\u003CREGION>:\u003CACCOUNT-ID>:log-group:/aws/codebuild/ci-container-build-project:log-stream:*\"\n}\n",[53,1062,1063,1067,1077,1088,1097],{"__ignoreMap":323},[327,1064,1065],{"class":329,"line":330},[327,1066,961],{"class":399},[327,1068,1069,1071,1073,1075],{"class":329,"line":336},[327,1070,966],{"class":403},[327,1072,400],{"class":399},[327,1074,971],{"class":441},[327,1076,974],{"class":399},[327,1078,1079,1081,1083,1086],{"class":329,"line":342},[327,1080,979],{"class":403},[327,1082,400],{"class":399},[327,1084,1085],{"class":441},"\"logs:GetLogEvents\"",[327,1087,974],{"class":399},[327,1089,1090,1092,1094],{"class":329,"line":348},[327,1091,991],{"class":403},[327,1093,400],{"class":399},[327,1095,1096],{"class":441},"\"arn:aws:logs:\u003CREGION>:\u003CACCOUNT-ID>:log-group:/aws/codebuild/ci-container-build-project:log-stream:*\"\n",[327,1098,1099],{"class":329,"line":354},[327,1100,1001],{"class":399},[12,1102,1103,1104,1107,1108,1111,1112,1115,1116,516,1119,1122],{},"The access credentials can be provided to AWS CLI through GitLab CI environment variables. Please go to your GitLab Project's ",[374,1105,1106],{},"CI/CD Settings",", click ",[374,1109,1110],{},"Expand"," in the ",[374,1113,1114],{},"Variables"," section, add ",[53,1117,1118],{},"AWS_ACCESS_KEY_ID",[53,1120,1121],{},"AWS_SECRET_ACCESS_KEY"," with the values you got from the AWS Management Console after creating the IAM user. See the image below for the result you can expect:",[12,1124,1125],{},[44,1126],{"alt":1127,"src":1128},"Providing AWS credentials for GitLab Runner","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398023/blog/Content%20Images/build-container-image-runner-fargate-codebuild-credentials.png",[12,1130,1131,1132,1137],{},"Using an IAM Role and ",[16,1133,1136],{"href":1134,"rel":1135},"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html",[],"Amazon ECS temporary/unique security credentials"," is also possible, but not covered in this tutorial.",[37,1139,1141],{"id":1140},"step-7-its-showtime","Step 7: It's showtime",[12,1143,1144],{},"With all configurations in place, commit the changes and trigger a new pipeline to watch the magic happen!",[506,1146,1148],{"id":1147},"just-need-the-highlights","Just need the highlights?",[93,1150,1151,1162,1171,1181],{},[72,1152,1153,1154,1158,1159],{},"The CI job script added in ",[16,1155,1157],{"href":1156},"#add-a-job-to-build-the-resulting-container","Step 5"," compresses the resulting container image build files into ",[53,1160,1161],{},"build.zip",[72,1163,1164,1166,1167],{},[53,1165,1161],{}," is then uploaded to the S3 Bucket we created in ",[16,1168,1170],{"href":1169},"#step-1-create-an-amazon-s3-bucket","Step 1: Create an Amazon S3 Bucket",[72,1172,1173,1174,1176,1177,1180],{},"Next, ",[53,1175,523],{}," starts a CodeBuild job based on the project created in ",[16,1178,151],{"href":1179},"#step-2-create-an-aws-codebuild-project"," (Note: that project has an S3 object as its source provider)",[72,1182,1183,1184,1186,1187,1189],{},"Finally, the CodeBuild job downloads ",[53,1185,206],{}," from S3, decompresses it and – from ",[53,1188,367],{},"– builds the resulting container image",[12,1191,1192,1193,26],{},"A sample repository, demonstrating everything described in the article is available ",[16,1194,1197],{"href":1195,"rel":1196},"https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/codebuild-on-fargate-example/",[],"here",[37,1199,1201],{"id":1200},"cleanup","Cleanup",[12,1203,1204],{},"If you want to perform a cleanup after testing the custom executor with AWS Fargate and CodeBuild, you should remove the following objects:",[69,1206,1207,1213,1219,1228,1237,1244,1254,1261],{},[72,1208,1209,1210],{},"AWS S3 bucket created in ",[16,1211,1212],{"href":1169},"Step 1",[72,1214,1215,1216],{},"AWS CodeBuild project created in ",[16,1217,1218],{"href":1179},"Step 2",[72,1220,1221,1224,1225],{},[53,1222,1223],{},"RUN"," command added to the CI container image in ",[16,1226,1227],{"href":929},"Step 3",[72,1229,74,1230,1232,1233],{},[53,1231,367],{}," file created in ",[16,1234,1236],{"href":1235},"#step-4-add-codebuild-configuration-to-the-repository","Step 4",[72,1238,74,1239,1232,1241],{},[53,1240,523],{},[16,1242,1157],{"href":1243},"#step-5-set-up-the-gitlab-ci-job",[72,1245,74,1246,1248,1249,1251,1252],{},[53,1247,849],{}," job added to ",[53,1250,839],{}," in ",[16,1253,1157],{"href":1243},[72,1255,1256,1257],{},"IAM policy, user (and maybe group) created in ",[16,1258,1260],{"href":1259},"#step-6-set-up-aws-credentials","Step 6",[72,1262,1263,1264],{},"GitLab CI/CD variables in ",[16,1265,1260],{"href":1259},[12,1267,1268,1269,1273,1274,1273,1279],{},"Read more about GitLab and AWS:\n-",[16,1270,1272],{"href":1271},"/blog/introducing-autoscaling-gitlab-runners-on-aws-fargate/","How autoscaling GitLab CI works on AWS Fargate","\n-",[16,1275,1278],{"href":1276,"rel":1277},"https://docs.gitlab.com/releases/",[],"GitLab 12.10 released with Requirements Management and Autoscaling CI on AWS Fargate",[16,1280,1282],{"href":1281},"/blog/gitlab-arm-aws-graviton2-solution/","Announcing 32/64-bit Arm Runner Support for AWS Graviton2",[12,1284,1285,1286,1291,1292],{},"Cover image by ",[16,1287,1290],{"href":1288,"rel":1289},"https://unsplash.com/@switch_dtp_fotografie",[],"Lucas van Oort"," on ",[16,1293,1296],{"href":1294,"rel":1295},"https://unsplash.com",[],"Unsplash",[1298,1299,1300],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}",{"title":323,"searchDepth":336,"depth":336,"links":1302},[1303,1304,1305,1306,1307,1308,1309,1313,1314,1317],{"id":39,"depth":336,"text":40},{"id":63,"depth":336,"text":64},{"id":90,"depth":336,"text":91},{"id":150,"depth":336,"text":151},{"id":289,"depth":336,"text":290},{"id":360,"depth":336,"text":361},{"id":500,"depth":336,"text":501,"children":1310},[1311,1312],{"id":508,"depth":342,"text":509},{"id":821,"depth":342,"text":822},{"id":938,"depth":336,"text":939},{"id":1140,"depth":336,"text":1141,"children":1315},[1316],{"id":1147,"depth":342,"text":1148},{"id":1200,"depth":336,"text":1201},"engineering","2020-07-31","Build containers with the AWS Fargate Custom Executor for GitLab Runner and AWS CodeBuild","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667132/Blog/Hero%20Images/build-container-image-runner-fargate-codebuild-cover.jpg",{},"/en-us/blog/aws-fargate-codebuild-build-containers-gitlab-runner",{"title":1328,"description":1320,"ogTitle":1328,"ogDescription":1320,"noIndex":1323,"ogImage":1324,"ogUrl":1329,"ogSiteName":1330,"ogType":1331,"canonicalUrls":1329},"Building containers with GitLab Runner & AWS Fargate executor","https://about.gitlab.com/blog/aws-fargate-codebuild-build-containers-gitlab-runner","https://about.gitlab.com","article","aws-fargate-codebuild-build-containers-gitlab-runner","en-us/blog/aws-fargate-codebuild-build-containers-gitlab-runner",[1335,1336,1337],"CI/CD","integrations","tutorial","BlogPost","VoBnLXgdaGdx917jdUHooj8MHANAEmeXiKEZdFAAf0U",{"logo":1341,"freeTrial":1346,"sales":1351,"login":1356,"items":1361,"search":1686,"minimal":1717,"duo":1736,"switchNav":1745,"pricingDeployment":1756},{"config":1342},{"href":1343,"dataGaName":1344,"dataGaLocation":1345},"/","gitlab logo","header",{"text":1347,"config":1348},"Get free trial",{"href":1349,"dataGaName":1350,"dataGaLocation":1345},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":1352,"config":1353},"Request a demo",{"href":1354,"dataGaName":1355,"dataGaLocation":1345},"/sales/?contact-topic=request-demo","sales",{"text":1357,"config":1358},"Sign in",{"href":1359,"dataGaName":1360,"dataGaLocation":1345},"https://gitlab.com/users/sign_in/","sign in",[1362,1391,1490,1495,1608,1664],{"text":1363,"config":1364,"menu":1366},"Platform",{"dataNavLevelOne":1365},"platform",{"type":1367,"columns":1368},"cards",[1369,1375,1383],{"title":1363,"description":1370,"link":1371},"The intelligent orchestration platform for DevSecOps",{"text":1372,"config":1373},"Explore our Platform",{"href":1374,"dataGaName":1365,"dataGaLocation":1345},"/platform/",{"title":1376,"description":1377,"link":1378},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1379,"config":1380},"Meet GitLab Duo",{"href":1381,"dataGaName":1382,"dataGaLocation":1345},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1384,"description":1385,"link":1386},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1387,"config":1388},"Learn more",{"href":1389,"dataGaName":1390,"dataGaLocation":1345},"/why-gitlab/","why gitlab",{"text":1392,"left":409,"config":1393,"menu":1395},"Product",{"dataNavLevelOne":1394},"solutions",{"type":1396,"link":1397,"columns":1401,"feature":1469},"lists",{"text":1398,"config":1399},"View all Solutions",{"href":1400,"dataGaName":1394,"dataGaLocation":1345},"/solutions/",[1402,1425,1448],{"title":1403,"description":1404,"link":1405,"items":1410},"Automation","CI/CD and automation to accelerate deployment",{"config":1406},{"icon":1407,"href":1408,"dataGaName":1409,"dataGaLocation":1345},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1411,1414,1417,1421],{"text":1335,"config":1412},{"href":1413,"dataGaLocation":1345,"dataGaName":1335},"/solutions/continuous-integration/",{"text":1376,"config":1415},{"href":1381,"dataGaLocation":1345,"dataGaName":1416},"gitlab duo agent platform - product menu",{"text":1418,"config":1419},"Source Code Management",{"href":1420,"dataGaLocation":1345,"dataGaName":1418},"/solutions/source-code-management/",{"text":1422,"config":1423},"Automated Software Delivery",{"href":1408,"dataGaLocation":1345,"dataGaName":1424},"Automated software delivery",{"title":1426,"description":1427,"link":1428,"items":1433},"Security","Deliver code faster without compromising security",{"config":1429},{"href":1430,"dataGaName":1431,"dataGaLocation":1345,"icon":1432},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1434,1438,1443],{"text":1435,"config":1436},"Application Security Testing",{"href":1430,"dataGaName":1437,"dataGaLocation":1345},"Application security testing",{"text":1439,"config":1440},"Software Supply Chain Security",{"href":1441,"dataGaLocation":1345,"dataGaName":1442},"/solutions/supply-chain/","Software supply chain security",{"text":1444,"config":1445},"Software Compliance",{"href":1446,"dataGaName":1447,"dataGaLocation":1345},"/solutions/software-compliance/","software compliance",{"title":1449,"link":1450,"items":1455},"Measurement",{"config":1451},{"icon":1452,"href":1453,"dataGaName":1454,"dataGaLocation":1345},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1456,1460,1464],{"text":1457,"config":1458},"Visibility & Measurement",{"href":1453,"dataGaLocation":1345,"dataGaName":1459},"Visibility and Measurement",{"text":1461,"config":1462},"Value Stream Management",{"href":1463,"dataGaLocation":1345,"dataGaName":1461},"/solutions/value-stream-management/",{"text":1465,"config":1466},"Analytics & Insights",{"href":1467,"dataGaLocation":1345,"dataGaName":1468},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1470,"type":1396,"items":1471},"GitLab for",[1472,1478,1484],{"text":1473,"config":1474},"Enterprise",{"icon":1475,"href":1476,"dataGaLocation":1345,"dataGaName":1477},"Building","/enterprise/","enterprise",{"text":1479,"config":1480},"Small Business",{"icon":1481,"href":1482,"dataGaLocation":1345,"dataGaName":1483},"Work","/small-business/","small business",{"text":1485,"config":1486},"Public Sector",{"icon":1487,"href":1488,"dataGaLocation":1345,"dataGaName":1489},"Organization","/solutions/public-sector/","public sector",{"text":1491,"config":1492},"Pricing",{"href":1493,"dataGaName":1494,"dataGaLocation":1345,"dataNavLevelOne":1494},"/pricing/","pricing",{"text":1496,"config":1497,"menu":1499},"Resources",{"dataNavLevelOne":1498},"resources",{"type":1396,"link":1500,"columns":1504,"feature":1597},{"text":1501,"config":1502},"View all resources",{"href":1503,"dataGaName":1498,"dataGaLocation":1345},"/resources/",[1505,1537,1564],{"title":1506,"items":1507},"Getting started",[1508,1513,1518,1523,1528,1533],{"text":1509,"config":1510},"Install",{"href":1511,"dataGaName":1512,"dataGaLocation":1345},"/install/","install",{"text":1514,"config":1515},"Quick start guides",{"href":1516,"dataGaName":1517,"dataGaLocation":1345},"/get-started/","quick setup checklists",{"text":1519,"config":1520},"Learn",{"href":1521,"dataGaLocation":1345,"dataGaName":1522},"https://university.gitlab.com/","learn",{"text":1524,"config":1525},"Product documentation",{"href":1526,"dataGaName":1527,"dataGaLocation":1345},"https://docs.gitlab.com/","product documentation",{"text":1529,"config":1530},"Best practice videos",{"href":1531,"dataGaName":1532,"dataGaLocation":1345},"/getting-started-videos/","best practice videos",{"text":1534,"config":1535},"Integrations",{"href":1536,"dataGaName":1336,"dataGaLocation":1345},"/integrations/",{"title":1538,"items":1539},"Discover",[1540,1545,1550,1555,1559],{"text":1541,"config":1542},"Customer success stories",{"href":1543,"dataGaName":1544,"dataGaLocation":1345},"/customers/","customer success stories",{"text":1546,"config":1547},"Blog",{"href":1548,"dataGaName":1549,"dataGaLocation":1345},"/blog/","blog",{"text":1551,"config":1552},"Demo Hub",{"href":1553,"dataGaName":1554,"dataGaLocation":1345},"/demo-hub/","demo hub",{"text":1556,"config":1557},"The Source",{"href":1558,"dataGaName":1549,"dataGaLocation":1345},"/the-source/",{"text":1560,"config":1561},"Remote",{"href":1562,"dataGaName":1563,"dataGaLocation":1345},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1565,"items":1566},"Connect",[1567,1572,1577,1582,1587,1592],{"text":1568,"config":1569},"GitLab Services",{"href":1570,"dataGaName":1571,"dataGaLocation":1345},"/services/","services",{"text":1573,"config":1574},"Contribute",{"href":1575,"dataGaName":1576,"dataGaLocation":1345},"https://contributors.gitlab.com","contribute",{"text":1578,"config":1579},"Community",{"href":1580,"dataGaName":1581,"dataGaLocation":1345},"/community/","community",{"text":1583,"config":1584},"Forum",{"href":1585,"dataGaName":1586,"dataGaLocation":1345},"https://forum.gitlab.com/","forum",{"text":1588,"config":1589},"Events",{"href":1590,"dataGaName":1591,"dataGaLocation":1345},"/events/","events",{"text":1593,"config":1594},"Partners",{"href":1595,"dataGaName":1596,"dataGaLocation":1345},"/partners/","partners",{"config":1598,"title":1601,"text":1602,"link":1603},{"background":1599,"textColor":1600},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":1604,"config":1605},"Read the latest",{"href":1606,"dataGaName":1607,"dataGaLocation":1345},"/whats-new/","whats new",{"text":1609,"config":1610,"menu":1612},"Company",{"dataNavLevelOne":1611},"company",{"type":1396,"columns":1613},[1614],{"items":1615},[1616,1621,1627,1629,1634,1639,1644,1649,1654,1659],{"text":1617,"config":1618},"About",{"href":1619,"dataGaName":1620,"dataGaLocation":1345},"/company/","about",{"text":1622,"config":1623,"footerGa":1626},"Jobs",{"href":1624,"dataGaName":1625,"dataGaLocation":1345},"/jobs/","jobs",{"dataGaName":1625},{"text":1588,"config":1628},{"href":1590,"dataGaName":1591,"dataGaLocation":1345},{"text":1630,"config":1631},"Leadership",{"href":1632,"dataGaName":1633,"dataGaLocation":1345},"/company/team/e-group/","leadership",{"text":1635,"config":1636},"Handbook",{"href":1637,"dataGaName":1638,"dataGaLocation":1345},"https://handbook.gitlab.com/","handbook",{"text":1640,"config":1641},"Investor relations",{"href":1642,"dataGaName":1643,"dataGaLocation":1345},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1645,"config":1646},"Trust Center",{"href":1647,"dataGaName":1648,"dataGaLocation":1345},"/security/","trust center",{"text":1650,"config":1651},"AI Transparency Center",{"href":1652,"dataGaName":1653,"dataGaLocation":1345},"/ai-transparency-center/","ai transparency center",{"text":1655,"config":1656},"Newsletter",{"href":1657,"dataGaName":1658,"dataGaLocation":1345},"/company/contact/#contact-forms","newsletter",{"text":1660,"config":1661},"Press",{"href":1662,"dataGaName":1663,"dataGaLocation":1345},"/press/","press",{"text":1665,"config":1666,"menu":1667},"Contact us",{"dataNavLevelOne":1611},{"type":1396,"columns":1668},[1669],{"items":1670},[1671,1676,1681],{"text":1672,"config":1673},"Talk to sales",{"href":1674,"dataGaName":1675,"dataGaLocation":1345},"/sales/","talk to sales",{"text":1677,"config":1678},"Support portal",{"href":1679,"dataGaName":1680,"dataGaLocation":1345},"https://support.gitlab.com/hc/en-us","support portal",{"text":1682,"config":1683},"Customer portal",{"href":1684,"dataGaName":1685,"dataGaLocation":1345},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1687,"login":1688,"suggestions":1695},"Close",{"text":1689,"link":1690},"To search repositories and projects, login to",{"text":1691,"config":1692},"gitlab.com",{"href":1359,"dataGaName":1693,"dataGaLocation":1694},"search login","search",{"text":1696,"default":1697},"Suggestions",[1698,1700,1704,1706,1710,1714],{"text":1376,"config":1699},{"href":1381,"dataGaName":1376,"dataGaLocation":1694},{"text":1701,"config":1702},"Code Suggestions (AI)",{"href":1703,"dataGaName":1701,"dataGaLocation":1694},"/solutions/code-suggestions/",{"text":1335,"config":1705},{"href":1413,"dataGaName":1335,"dataGaLocation":1694},{"text":1707,"config":1708},"GitLab on AWS",{"href":1709,"dataGaName":1707,"dataGaLocation":1694},"/partners/technology-partners/aws/",{"text":1711,"config":1712},"GitLab on Google Cloud",{"href":1713,"dataGaName":1711,"dataGaLocation":1694},"/partners/technology-partners/google-cloud-platform/",{"text":1715,"config":1716},"Why GitLab?",{"href":1389,"dataGaName":1715,"dataGaLocation":1694},{"freeTrial":1718,"mobileIcon":1723,"desktopIcon":1728,"secondaryButton":1731},{"text":1719,"config":1720},"Start free trial",{"href":1721,"dataGaName":1350,"dataGaLocation":1722},"https://gitlab.com/-/trials/new/","nav",{"altText":1724,"config":1725},"Gitlab Icon",{"src":1726,"dataGaName":1727,"dataGaLocation":1722},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1724,"config":1729},{"src":1730,"dataGaName":1727,"dataGaLocation":1722},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1732,"config":1733},"Get Started",{"href":1734,"dataGaName":1735,"dataGaLocation":1722},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1737,"mobileIcon":1741,"desktopIcon":1743},{"text":1738,"config":1739},"Learn more about GitLab Duo",{"href":1381,"dataGaName":1740,"dataGaLocation":1722},"gitlab duo",{"altText":1724,"config":1742},{"src":1726,"dataGaName":1727,"dataGaLocation":1722},{"altText":1724,"config":1744},{"src":1730,"dataGaName":1727,"dataGaLocation":1722},{"button":1746,"mobileIcon":1751,"desktopIcon":1753},{"text":1747,"config":1748},"/switch",{"href":1749,"dataGaName":1750,"dataGaLocation":1722},"#contact","switch",{"altText":1724,"config":1752},{"src":1726,"dataGaName":1727,"dataGaLocation":1722},{"altText":1724,"config":1754},{"src":1755,"dataGaName":1727,"dataGaLocation":1722},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1757,"mobileIcon":1762,"desktopIcon":1764},{"text":1758,"config":1759},"Back to pricing",{"href":1493,"dataGaName":1760,"dataGaLocation":1722,"icon":1761},"back to pricing","GoBack",{"altText":1724,"config":1763},{"src":1726,"dataGaName":1727,"dataGaLocation":1722},{"altText":1724,"config":1765},{"src":1730,"dataGaName":1727,"dataGaLocation":1722},{"title":1767,"titleMobile":1768,"button":1769,"config":1774},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1387,"config":1770},{"href":1771,"dataGaName":1772,"dataGaLocation":1773},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1775,"disabled":1323},"release",{"data":1777},{"text":1778,"source":1779,"edit":1785,"contribute":1790,"config":1795,"items":1800,"minimal":2009},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1780,"config":1781},"View page source",{"href":1782,"dataGaName":1783,"dataGaLocation":1784},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1786,"config":1787},"Edit this page",{"href":1788,"dataGaName":1789,"dataGaLocation":1784},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1791,"config":1792},"Please contribute",{"href":1793,"dataGaName":1794,"dataGaLocation":1784},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1796,"facebook":1797,"youtube":1798,"linkedin":1799},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1801,1848,1901,1945,1977],{"title":1491,"links":1802,"subMenu":1817},[1803,1807,1812],{"text":1804,"config":1805},"View plans",{"href":1493,"dataGaName":1806,"dataGaLocation":1784},"view plans",{"text":1808,"config":1809},"Why Premium?",{"href":1810,"dataGaName":1811,"dataGaLocation":1784},"/pricing/premium/","why premium",{"text":1813,"config":1814},"Why Ultimate?",{"href":1815,"dataGaName":1816,"dataGaLocation":1784},"/pricing/ultimate/","why ultimate",[1818],{"title":1819,"links":1820},"Contact Us",[1821,1824,1826,1828,1833,1838,1843],{"text":1822,"config":1823},"Contact sales",{"href":1674,"dataGaName":1355,"dataGaLocation":1784},{"text":1677,"config":1825},{"href":1679,"dataGaName":1680,"dataGaLocation":1784},{"text":1682,"config":1827},{"href":1684,"dataGaName":1685,"dataGaLocation":1784},{"text":1829,"config":1830},"Status",{"href":1831,"dataGaName":1832,"dataGaLocation":1784},"https://status.gitlab.com/","status",{"text":1834,"config":1835},"Terms of use",{"href":1836,"dataGaName":1837,"dataGaLocation":1784},"/terms/","terms of use",{"text":1839,"config":1840},"Privacy statement",{"href":1841,"dataGaName":1842,"dataGaLocation":1784},"/privacy/","privacy statement",{"text":1844,"config":1845},"Cookie preferences",{"dataGaName":1846,"dataGaLocation":1784,"id":1847,"isOneTrustButton":409},"cookie preferences","ot-sdk-btn",{"title":1392,"links":1849,"subMenu":1858},[1850,1854],{"text":1851,"config":1852},"DevSecOps platform",{"href":1374,"dataGaName":1853,"dataGaLocation":1784},"devsecops platform",{"text":1855,"config":1856},"AI-Assisted Development",{"href":1381,"dataGaName":1857,"dataGaLocation":1784},"ai-assisted development",[1859],{"title":1860,"links":1861},"Topics",[1862,1866,1871,1876,1881,1886,1891,1896],{"text":1863,"config":1864},"CICD",{"href":24,"dataGaName":1865,"dataGaLocation":1784},"cicd",{"text":1867,"config":1868},"GitOps",{"href":1869,"dataGaName":1870,"dataGaLocation":1784},"/topics/gitops/","gitops",{"text":1872,"config":1873},"DevOps",{"href":1874,"dataGaName":1875,"dataGaLocation":1784},"/topics/devops/","devops",{"text":1877,"config":1878},"Version Control",{"href":1879,"dataGaName":1880,"dataGaLocation":1784},"/topics/version-control/","version control",{"text":1882,"config":1883},"DevSecOps",{"href":1884,"dataGaName":1885,"dataGaLocation":1784},"/topics/devsecops/","devsecops",{"text":1887,"config":1888},"Cloud Native",{"href":1889,"dataGaName":1890,"dataGaLocation":1784},"/topics/cloud-native/","cloud native",{"text":1892,"config":1893},"AI for Coding",{"href":1894,"dataGaName":1895,"dataGaLocation":1784},"/topics/devops/ai-for-coding/","ai for coding",{"text":1897,"config":1898},"Agentic AI",{"href":1899,"dataGaName":1900,"dataGaLocation":1784},"/topics/agentic-ai/","agentic ai",{"title":1902,"links":1903},"Solutions",[1904,1906,1908,1913,1917,1920,1924,1927,1929,1932,1935,1940],{"text":1435,"config":1905},{"href":1430,"dataGaName":1435,"dataGaLocation":1784},{"text":1424,"config":1907},{"href":1408,"dataGaName":1409,"dataGaLocation":1784},{"text":1909,"config":1910},"Agile development",{"href":1911,"dataGaName":1912,"dataGaLocation":1784},"/solutions/agile-delivery/","agile delivery",{"text":1914,"config":1915},"SCM",{"href":1420,"dataGaName":1916,"dataGaLocation":1784},"source code management",{"text":1863,"config":1918},{"href":1413,"dataGaName":1919,"dataGaLocation":1784},"continuous integration & delivery",{"text":1921,"config":1922},"Value stream management",{"href":1463,"dataGaName":1923,"dataGaLocation":1784},"value stream management",{"text":1867,"config":1925},{"href":1926,"dataGaName":1870,"dataGaLocation":1784},"/solutions/gitops/",{"text":1473,"config":1928},{"href":1476,"dataGaName":1477,"dataGaLocation":1784},{"text":1930,"config":1931},"Small business",{"href":1482,"dataGaName":1483,"dataGaLocation":1784},{"text":1933,"config":1934},"Public sector",{"href":1488,"dataGaName":1489,"dataGaLocation":1784},{"text":1936,"config":1937},"Education",{"href":1938,"dataGaName":1939,"dataGaLocation":1784},"/solutions/education/","education",{"text":1941,"config":1942},"Financial services",{"href":1943,"dataGaName":1944,"dataGaLocation":1784},"/solutions/finance/","financial services",{"title":1496,"links":1946},[1947,1949,1951,1953,1956,1958,1961,1963,1965,1967,1969,1971,1973,1975],{"text":1509,"config":1948},{"href":1511,"dataGaName":1512,"dataGaLocation":1784},{"text":1514,"config":1950},{"href":1516,"dataGaName":1517,"dataGaLocation":1784},{"text":1519,"config":1952},{"href":1521,"dataGaName":1522,"dataGaLocation":1784},{"text":1524,"config":1954},{"href":1526,"dataGaName":1955,"dataGaLocation":1784},"docs",{"text":1546,"config":1957},{"href":1548,"dataGaName":1549,"dataGaLocation":1784},{"text":1959,"config":1960},"What's new",{"href":1606,"dataGaName":1607,"dataGaLocation":1784},{"text":1541,"config":1962},{"href":1543,"dataGaName":1544,"dataGaLocation":1784},{"text":1560,"config":1964},{"href":1562,"dataGaName":1563,"dataGaLocation":1784},{"text":1568,"config":1966},{"href":1570,"dataGaName":1571,"dataGaLocation":1784},{"text":1573,"config":1968},{"href":1575,"dataGaName":1576,"dataGaLocation":1784},{"text":1578,"config":1970},{"href":1580,"dataGaName":1581,"dataGaLocation":1784},{"text":1583,"config":1972},{"href":1585,"dataGaName":1586,"dataGaLocation":1784},{"text":1588,"config":1974},{"href":1590,"dataGaName":1591,"dataGaLocation":1784},{"text":1593,"config":1976},{"href":1595,"dataGaName":1596,"dataGaLocation":1784},{"title":1609,"links":1978},[1979,1981,1983,1985,1987,1989,1993,1998,2000,2002,2004],{"text":1617,"config":1980},{"href":1619,"dataGaName":1611,"dataGaLocation":1784},{"text":1622,"config":1982},{"href":1624,"dataGaName":1625,"dataGaLocation":1784},{"text":1630,"config":1984},{"href":1632,"dataGaName":1633,"dataGaLocation":1784},{"text":1635,"config":1986},{"href":1637,"dataGaName":1638,"dataGaLocation":1784},{"text":1640,"config":1988},{"href":1642,"dataGaName":1643,"dataGaLocation":1784},{"text":1990,"config":1991},"Sustainability",{"href":1992,"dataGaName":1990,"dataGaLocation":1784},"/sustainability/",{"text":1994,"config":1995},"Diversity, inclusion and belonging (DIB)",{"href":1996,"dataGaName":1997,"dataGaLocation":1784},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1645,"config":1999},{"href":1647,"dataGaName":1648,"dataGaLocation":1784},{"text":1655,"config":2001},{"href":1657,"dataGaName":1658,"dataGaLocation":1784},{"text":1660,"config":2003},{"href":1662,"dataGaName":1663,"dataGaLocation":1784},{"text":2005,"config":2006},"Modern Slavery Transparency Statement",{"href":2007,"dataGaName":2008,"dataGaLocation":1784},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":2010},[2011,2014,2017],{"text":2012,"config":2013},"Terms",{"href":1836,"dataGaName":1837,"dataGaLocation":1784},{"text":2015,"config":2016},"Cookies",{"dataGaName":1846,"dataGaLocation":1784,"id":1847,"isOneTrustButton":409},{"text":2018,"config":2019},"Privacy",{"href":1841,"dataGaName":1842,"dataGaLocation":1784},[2021],{"id":2022,"title":7,"body":1322,"config":2023,"content":2025,"description":1322,"extension":2028,"meta":2029,"navigation":409,"path":2030,"seo":2031,"stem":2032,"__hash__":2033},"blogAuthors/en-us/blog/authors/elliot-rushton.yml",{"template":2024},"BlogAuthor",{"name":7,"config":2026},{"headshot":323,"ctfId":2027},"erushton","yml",{},"/en-us/blog/authors/elliot-rushton",{},"en-us/blog/authors/elliot-rushton","O7-wa1rcYIL9-99-cqwVLGVd36T5uwkYvnesoGNo9fM",[2035,2044,2052],{"title":2036,"description":2037,"heroImage":2038,"category":1318,"date":2039,"authors":2040,"slug":2043,"externalUrl":1322},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[2041,2042],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":2045,"description":2046,"heroImage":2047,"category":1318,"date":2048,"authors":2049,"slug":2051,"externalUrl":1322},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[2050],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":2053,"description":2054,"heroImage":2055,"category":1318,"date":2056,"authors":2057,"slug":2059,"externalUrl":1322},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[2058],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":2061},[2062,2076,2088,2100],{"id":2063,"categories":2064,"header":2066,"text":2067,"button":2068,"image":2073},"ai-modernization",[2065],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":2069,"config":2070},"Get your AI maturity score",{"href":2071,"dataGaName":2072,"dataGaLocation":1549},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":2074},{"src":2075},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":2077,"categories":2078,"header":2080,"text":2067,"button":2081,"image":2085},"devops-modernization",[2079,1885],"product","Are you just managing tools or shipping innovation?",{"text":2082,"config":2083},"Get your DevOps maturity score",{"href":2084,"dataGaName":2072,"dataGaLocation":1549},"/assessments/devops-modernization-assessment/",{"config":2086},{"src":2087},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":2089,"categories":2090,"header":2092,"text":2067,"button":2093,"image":2097},"security-modernization",[2091],"security","Are you trading speed for security?",{"text":2094,"config":2095},"Get your security maturity score",{"href":2096,"dataGaName":2072,"dataGaLocation":1549},"/assessments/security-modernization-assessment/",{"config":2098},{"src":2099},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":2101,"paths":2102,"header":2105,"text":2106,"button":2107,"image":2112},"github-azure-migration",[2103,2104],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":2108,"config":2109},"See how GitLab compares to GitHub",{"href":2110,"dataGaName":2111,"dataGaLocation":1549},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":2113},{"src":2087},{"header":2115,"blurb":2116,"button":2117,"secondaryButton":2122},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":2118,"config":2119},"Get your free trial",{"href":2120,"dataGaName":1350,"dataGaLocation":2121},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1822,"config":2123},{"href":1674,"dataGaName":1355,"dataGaLocation":2121},1786803747666]