> For the complete documentation index, see [llms.txt](https://docs.duplocloud.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.duplocloud.com/docs/automation-platform/introduction-to-ci-cd/gitlab-ci-cd/build-a-docker-image.md).

# Build a Docker image

Use Duplo to build and push a docker image from Gitlab CI/CD

## Case: Build and Push to DockerHub

The goal of this section is to show how you can build a docker image and push it to DockerHub.

It does three basic things:

* Logs in to DockerHub
* Builds and tags your docker image, with the tag based on the git commit SHA.
* Pushes your docker image

### Example Workflow

Here is an example gitlab workflow that builds a docker image and pushes it to DockerHub.

To use it you will need to change:

* `DOCKERHUB_USERNAME`variable
* `DOCKERHUB_REPO`variable
* `DUPLO_HOST`variable
* `DUPLO_SERVICE_NAME`variable
* `TENANT_NAME`variable

```yaml
variables:
  DOCKERHUB_USERNAME: duplocloud               # CHANGE ME!
  DOCKERHUB_REPO: mydockerhubid/myrepo         # CHANGE ME!
  DUPLO_HOST: https://mysystem.duplocloud.net  # CHANGE ME!
  DUPLO_SERVICE_NAME: myservice                # CHANGE ME!
  TENANT_NAME: mytenant                        # CHANGE ME!

docker-build:
  # Use the official docker image.
  image: docker:latest
  stage: build
  services:
    - docker:dind
  before_script:
    - docker login -u "$DOCKERHUB_USERNAME" -p "$DOCKERHUB_PASSWORD"
  script:
    - |
      tag=":$CI_COMMIT_SHA"
      echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
    - docker build --pull -t "$DOCKERHUB_REPO${tag}" .
    - docker push "$DOCKERHUB_REPO${tag}"
  # Run this job in a branch where a Dockerfile exists
  rules:
    - if: $CI_COMMIT_BRANCH
      exists:
        - Dockerfile
```

## Case: Build and Push to Amazon ECR (Elastic Container Registry)

The goal of this section is to show how you can build a docker image and push it to Amazon ECR.

It does three basic things:

* Logs in to Amazon ECR
* Builds and tags your docker image, with the tag based on the GitLab CI Pipeline execution id.
* Pushes your docker image to ECR

*Prerequisite - A repository in ECR must have been created before proceeding with the next steps.*

This process uses DuploCloud API Token (refer [DuploCloud API Token](https://docs.duplocloud.com/docs/administrators/access-control/api-tokens#permanent-api-tokens)) to gain access to AWS ECR.

Go to GitLab > Settings > CI CD > Variables > Expand and ensure that DUPLO\_TOKEN variable is set and has correct value. Check the Protect Variable and Masked options for security purposes. You can refer to [Configuring GitLab](https://docs.duplocloud.com/docs/ci-cd/github-actions-1/configuring-github) for the steps to setup a service account and to create a token for the newly configured account. The service account must have admin role.

The script uses amazon/aws-cli image as the base running image and uses Docker-in-Docker (docker/dind) to run the Docker commands. It uses duplo\_utils.sh script from DuploCloud to get configuration from the DuploCloud instance.

### Example Workflow

Here is an example gitlab workflow that builds a docker image and pushes it to DockerHub.

To use it you will need to change:

* `DOCKER_REGISTRY`variable
* `DOCKER_REPO` variable
* `DUPLO_HOST` variable
* `DUPLO_SERVICE_NAME` variable
* `TENANT_NAME` variable
* `AWS_DEFAULT_REGION`variable
* `APP_NAME`variable

```yaml
variables:
  DOCKER_REGISTRY: <xxxxxxxxxxx>.dkr.ecr.<ecr repo region>.amazonaws.com
  DOCKER_REPO: <xxxxxxxxxxx>.dkr.ecr.<ecr repo region>.amazonaws.com/xxx-yyy
  AWS_DEFAULT_REGION: <duplo master aws region>
  AWS_ECR_REGION: <ECR region>
  APP_NAME: <repo name>
  DUPLO_HOST: https://<instance>.duplocloud.net  
  DUPLO_SERVICE_NAME: <duplo service name>
  TENANT_NAME: <Tenant Name>
  DOCKER_HOST: tcp://docker:2375

stages:
  - build
  - deploy

build-and-push-job:
  stage: build
  image:
    name: amazon/aws-cli
    entrypoint: [""]
  services:
    - docker:dind
  before_script:
    - yum install -y wget jq
    - amazon-linux-extras install docker
    - wget https://raw.githubusercontent.com/duplocloud/demo-npm-service/master/.circleci/duplo_utils.sh
    - chmod +x duplo_utils.sh
    - source duplo_utils.sh
    - with_aws>tmp.txt  #Get secrets using with_aws script from source duplo_utils.sh
    - cat tmp.txt
    - cat tmp.txt|grep -i AWS_>tmp1.txt
    - cat tmp1.txt
    - source tmp1.txt
    - export $(cut -d= -f1 tmp1.txt)
    - aws ecr get-login-password --region $AWS_ECR_REGION | docker login --username AWS --password-stdin $DOCKER_REGISTRY
    - rm tmp.txt tmp1.txt   #remove the secrets from the runner
  script:
    - |
      tag="$CI_PIPELINE_IID"
      echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
    - docker build -t "$DOCKER_REGISTRY/$APP_NAME:${tag}" ./nginx/
    - docker push "$DOCKER_REGISTRY/$APP_NAME:${tag}"
    - docker logout #For security
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.duplocloud.com/docs/automation-platform/introduction-to-ci-cd/gitlab-ci-cd/build-a-docker-image.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
