1.2 CodeBuild Projects, Build Environments & Pipeline Secrets

Key Takeaways

  • AWS CodeBuild executes builds inside managed or custom ephemeral Docker containers governed by buildspec.yml, executing across four sequential phases: install, pre_build, build, and post_build.
  • Building container images within CodeBuild (Docker-in-Docker) strictly requires setting privilegedMode: true in the project environment configuration and granting ECR repository access to the build service role.
  • Attaching CodeBuild to a VPC enables private connectivity to internal resources like RDS databases and artifact repositories, but requires a NAT Gateway or VPC endpoints for internet access; containers in public subnets do not receive public IP addresses.
  • Build acceleration relies on dependency caching: Amazon S3 cache provides durable storage across distributed build fleets, while Local caching (LOCAL_DOCKER_LAYER_CACHE, LOCAL_CUSTOM_CACHE) delivers optimal speed for sequential builds on the same host.
  • Sensitive credentials must be retrieved dynamically in buildspec.yml using parameter-store for Systems Manager parameters and secrets-manager for Secrets Manager secrets, preventing secrets from leaking into source code or build logs.
Last updated: September 2026

AWS CodeBuild Fundamentals & buildspec.yml Anatomy

AWS CodeBuild is a fully managed, serverless build service that provisions isolated, ephemeral compute containers, executes specified commands, produces build artifacts, and streams logs to Amazon CloudWatch. CodeBuild scales elastically to handle concurrent build workloads without requiring management of dedicated build servers.

The buildspec.yml Lifecycle and Phases

A buildspec.yml file is a YAML-formatted configuration placed in the root of the source directory (or defined inline in the project). It coordinates the lifecycle of the build through four strictly ordered phases:

version: 0.2

env:
  variables:
    APP_ENV: "production"
    JAVA_OPTS: "-Xmx2048m"
  parameter-store:
    DB_USER: "/app/prod/db_user"
  secrets-manager:
    DB_PASSWORD: "prod/rds/credentials:password"
  exported-variables:
    - IMAGE_TAG
    - BUILD_TIMESTAMP

phases:
  install:
    run-as: root
    runtime-versions:
      java: corretto17
      nodejs: 20
    commands:
      - echo "Installing build dependencies and tools..."
      - apt-get update && apt-get install -y jq
      - npm install -g snyk
  pre_build:
    commands:
      - echo "Executing pre-build verifications and authentications..."
      - aws --version
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - export IMAGE_TAG=${COMMIT_HASH:=latest}
      - export BUILD_TIMESTAMP=$(date +%s)
  build:
    commands:
      - echo "Compiling application and running test suites..."
      - mvn clean package -DskipTests=false
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo "Build completed on $(date)"
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - printf '[{"name":"microservice","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json

reports:
  surefire-reports:
    files:
      - '**/*'
    base-directory: 'target/surefire-reports'
    file-format: JUNITXML

artifacts:
  files:
    - imagedefinitions.json
    - target/*.jar
    - appspec.yml
  discard-paths: no

cache:
  paths:
    - '/root/.m2/**/*'
    - '/root/.npm/**/*'

Phase Behavior and Failure Control

  • Phase Sequence: install -> pre_build -> build -> post_build.
  • Failure Semantics: If any command within install, pre_build, or build exits with a non-zero status code, that phase immediately halts. By default, subsequent phases are skipped, and the build status transitions to FAILED.
  • The finally Block: Commands placed in a finally block execute regardless of whether commands in the main phase succeeded or failed. This is critical for releasing locks, flushing telemetry, or publishing test results.
  • on-failure: CONTINUE: Configuring on-failure: CONTINUE allows the phase to proceed even if individual commands fail, which is useful when generating test reports that must be evaluated downstream.

Custom Docker Build Environments & ECR

CodeBuild provides managed Docker images for standard runtimes (Amazon Linux 2, Amazon Linux 2023, Ubuntu). However, enterprise workflows frequently require custom compilers, specialized CLI tooling, or proprietary security agents.

Custom Docker Images from Amazon ECR

Organizations build hardened Docker images, store them in a private Amazon ECR repository, and configure the CodeBuild project environment to use the custom image:

  1. ECR Permissions: The CodeBuild service role requires IAM permissions to authenticate and pull the image (ecr:GetAuthorizationToken, ecr:BatchCheckLayerAvailability, ecr:GetDownloadUrlForLayer, and ecr:BatchGetImage).
  2. Cross-Account ECR: If the custom image resides in a shared security/tools account, the ECR repository policy must explicitly grant ecr:BatchGetImage and layer download permissions to the CodeBuild project service role in the build account.

Privileged Mode (Docker-in-Docker)

[!IMPORTANT] DOP-C02 Exam Trap: If your CodeBuild project builds Docker images, interacts with the Docker daemon, or executes Docker Compose commands, you must explicitly enable the privilegedMode flag (privilegedMode: true in CloudFormation/Terraform, or checking the "Privileged" box in the AWS Console). Without privilegedMode, the build container cannot access /var/run/docker.sock or launch the nested Docker daemon, resulting in the error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock.


VPC Support for Private Resource Access

By default, CodeBuild containers execute in an AWS-managed VPC with direct access to the public internet, public AWS service endpoints, and public Git repositories. However, builds frequently require access to private VPC resources, such as:

  • Amazon RDS / Aurora databases to execute schema migration scripts.
  • Internal package repositories (e.g., self-hosted Sonatype Nexus or JFrog Artifactory).
  • Private Amazon ElastiCache clusters or internal microservices.

The VPC Public Subnet Internet Black Hole

When you configure CodeBuild to attach to a VPC, CodeBuild provisions Elastic Network Interfaces (ENIs) inside your specified subnets.

[ CodeBuild Project in VPC ]
           │
           ▼ (Uses ENI)
    [ Private Subnet ]
           │
     Route: 0.0.0.0/0
           │
           ▼
    [ NAT Gateway ] ──> [ Internet Gateway ] ──> [ Public Internet ]
           │                                     (npm, pip, GitHub)
           ▼
[ VPC Gateway/Interface Endpoints ] ──> [ S3, ECR, CloudWatch Logs ]

[!CAUTION] Critical VPC Networking Rule: CodeBuild ENIs never receive public IPv4 addresses. Even if you place CodeBuild in a public subnet with an Internet Gateway route (0.0.0.0/0 -> igw-xxx), the build container cannot reach the internet because it lacks a public IP for address translation. External requests (e.g., npm install, pip install, docker pull) will hang and time out!

To enable internet access for a VPC-attached CodeBuild project:

  1. Attach CodeBuild to private subnets.
  2. Configure the private subnet route table with 0.0.0.0/0 pointing to an Amazon VPC NAT Gateway in a public subnet.
  3. Alternatively, for AWS-internal traffic, configure VPC Endpoints for Amazon S3, Amazon ECR, and CloudWatch Logs.

Dependency Caching Strategies

Build execution duration directly impacts developer feedback loops and AWS billing. CodeBuild supports two distinct caching mechanisms:

Cache MechanismScopeLatencyRecommended Use Case
Amazon S3 CacheDistributed across all build hosts; durable in S3Moderate (S3 upload/download time on build start/end)Intermittent builds, multi-account build fleets, or builds distributed across multiple regions
Local CacheStored on the local EC2 host running the build containerUltra-low (direct NVMe/SSD block storage access)High-frequency builds where successive builds likely run on the same underlying host

Local Cache Modes

Local caching offers three distinct configuration options:

  • LOCAL_DOCKER_LAYER_CACHE: Caches intermediate Docker build layers locally. Eliminates re-pulling and re-building unmodified layers in Dockerfile stages.
  • LOCAL_SOURCE_CACHE: Caches the Git source repository metadata, avoiding a complete re-clone of the entire repository on sequential builds.
  • LOCAL_CUSTOM_CACHE: Caches arbitrary directories defined in buildspec.yml under cache: paths, such as ~/.m2 (Maven), ~/.npm (Node), or ~/.cache/pip (Python).

Note: Local cache is maintained on a best-effort basis. If AWS provisions the build on a fresh underlying host due to scaling or maintenance, the local cache will be cold.


Secure Secrets Retrieval in CodeBuild

Hardcoding API tokens, database passwords, or private signing keys in buildspec.yml or source code is a critical security vulnerability. CodeBuild provides native integration with AWS Systems Manager Parameter Store and AWS Secrets Manager through the env block:

env:
  parameter-store:
    # Key: Environment variable name in build
    # Value: Parameter Store parameter name or ARN
    API_ENDPOINT: "/config/prod/api_endpoint"
    DATABASE_USER: "/config/prod/db_username"
  secrets-manager:
    # Key: Environment variable name in build
    # Value: SecretName:SecretKey:VersionStage:VersionId
    DB_PASSWORD: "prod/app/rds:password"
    GITHUB_PAT: "prod/vcs/tokens:github_token"

Operational and Security Benefits

  • Automatic Decryption: For SecureString parameters in Parameter Store and secrets in Secrets Manager, CodeBuild automatically requests decryption using the KMS key associated with the secret, provided the CodeBuild service role has kms:Decrypt permissions.
  • Log Masking: Secrets retrieved via parameter-store and secrets-manager are automatically masked in CloudWatch Logs output. If a command echoes $DB_PASSWORD, CloudWatch Logs displays *** instead of the plaintext credential.
  • Exported Variables: Values generated during the build (such as $IMAGE_TAG) listed under env: exported-variables are exported to downstream CodePipeline actions, enabling dynamic variable propagation.

Compute Types, Architectures & Batch Builds

CodeBuild provides flexible compute configurations to balance cost and compilation performance:

  • Compute Types: BUILD_GENERAL1_SMALL (2 vCPU, 4 GiB RAM), BUILD_GENERAL1_MEDIUM (4 vCPU, 8 GiB RAM), BUILD_GENERAL1_LARGE (8 vCPU, 16 GiB RAM), BUILD_GENERAL1_XLARGE (36 vCPU, 72 GiB RAM), and BUILD_GENERAL1_2XLARGE (72 vCPU, 144 GiB RAM).
  • Architectures: x86_64 (LINUX_CONTAINER), ARM64 (ARM_CONTAINER powered by AWS Graviton for native multi-architecture builds and cost efficiency), and Windows Server (WINDOWS_SERVER_2019_CONTAINER).

Batch Builds: Matrices and Graphs

For large-scale testing across matrix configurations, CodeBuild supports Batch Builds:

  • Build Matrix: Runs multiple parallel builds across permutations of operating systems, language versions, and test suites (e.g., testing across Node 18, 20, and 22 on both Linux and ARM64).
  • Build Graph (DAG): Defines a directed acyclic graph of dependent builds where downstream builds execute only after upstream prerequisites succeed (e.g., compile code -> run unit tests & SAST in parallel -> package container image).
Loading diagram...
AWS CodeBuild Architecture, Networking & Secrets Resolution
Test Your Knowledge

A DevOps engineer moves an existing AWS CodeBuild project into a corporate Amazon VPC so that the build phase can run automated database migration scripts against an Amazon RDS PostgreSQL database in a private subnet. The CodeBuild project is configured with the VPC ID, two public subnets with direct routes to an Internet Gateway, and a security group allowing outbound traffic to the database. When the build runs, the database migration succeeds, but the subsequent step npm install fails with connection timeout errors while attempting to fetch packages from the public npm registry. What is the root cause of this failure and the most architecturally appropriate resolution?

A
B
C
D
Test Your Knowledge

A software development team is migrating their containerized microservice build pipeline to AWS CodeBuild. The buildspec.yml executes docker build -t my-app:latest . and docker push <account-id>.dkr.ecr.<region>.amazonaws.com/my-app:latest. When the build executes, the CodeBuild project fails immediately during the docker build command with the error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? What configuration change must the DevOps engineer make to resolve this issue?

A
B
C
D
Test Your Knowledge

An organization requires that all database credentials used during automated integration testing in AWS CodeBuild be dynamically retrieved from AWS Secrets Manager without exposing passwords in source code, buildspec definitions, or build logs. The secret is stored under the name prod/db/credentials as a JSON object containing keys username and password. Which buildspec.yml configuration correctly injects the database password into an environment variable named DB_PASSWORD?

A
B
C
D