I’m going to create a Docker container infrastructure for CI/CD. Let’s assume we already have a Docker installation with Portainer.
Essential Containers for CI/CD:
- GitLab CE
- 
Function: Code repository + pipeline management.
 - 
Image:
gitlab/gitlab-ce - 
Ports:
- 
80: HTTP (web interface)
 - 
443: HTTPS (web interface)
 - 
22: SSH (clone the repository and commit to the remote)
 
 - 
 - 
Considerations:
- Mount volumes for persistent data:
- /etc/gitlab
 - /var/opt/gitlab
 - var/log/gitlab
 
 
 - Mount volumes for persistent data:
 
 - 
 - GitLab Runner
- 
Function: Executes pipeline jobs (build, test, deploy, etc.)
 - 
Image:
gitlab/gitlab-runner - 
Execution types:
- 
Docker: Each job runs inside a separate container. (I’ll use this one.)
 - 
Shell: Jobs run directly on the host (or container).
 
 - 
 
 - 
 
Recommended Folder Structure:
/infra-ci-cd/
│
├── docker-compose.yml
├── gitlab/
│     ├── config/
│     ├── logs/
│     └── data/
│
└── runner/
└── config/
Container Creation
#docker-compose.yml
services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    restart: always
    hostname: 'gitlab.local'
    ports:
      - '880:80'
      - '8443:443'
      - '822:22'
    volumes:
      - './gitlab/config:/etc/gitlab'
      - './gitlab/logs:/var/log/gitlab'
      - './gitlab/data:/var/opt/gitlab'
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    restart: always
    volumes:
      - './runner/config:/etc/gitlab-runner'
      - '/var/run/docker.sock:/var/run/docker.sock'
I’ve specified different ports on the local machine mapped to the necessary container ports to avoid conflicts:
ports:
  - '880:80'
  - '8443:443'
  - '822:22'
Once everything is set up, run:
docker compose up -d
This will start the containers, which we can view in Portainer.

Accessing GitLab
In the /etc/hosts file, I configure the domain gitlab.local to access it via the web browser.
#/etc/hosts
127.0.0.1 gitlab.local
To obtain the root password automatically created by GitLab, run:
docker exec -it [nom_contenidor_gitlab] grep 'Password:' /etc/gitlab/initial_root_password
You can now access http://gitlab.local:880 and log in with the root user and the retrieved password. Next, I create a blank project for the API (I’ll create a new project for the frontend in next steps):

In the next part, I’ll make the first commit to configure the pipelines.
