Solo para visitantes de nuestro blog Obtenga 3 meses adicionales gratis + 10% de descuento en el plan trianual YSBLOG10
Agarra el trato

Cómo crear CI/CD en un servidor Linux con Docker y Git

Última actualización: marzo 7, 2026 11 minutos de lectura Sanjeet Chauhan
Cómo crear CI/CD en un servidor Linux con Docker y Git

Para crear CI/CD en un servidor Linux, aprovisione un host seguro, conecte su repositorio Git, instale un ejecutor o orquestador de CI (Jenkins, GitHub Actions Runner o GitLab Runner), defina trabajos de canalización o YAML para compilar, probar y empaquetar su aplicación, luego implemente en staging/production a través de SSH o contenedores, con secretos managemiento, reversión y monitoreo.

En esta guía, aprenderá a crear CI/CD en un servidor Linux utilizando prácticas DevOps comprobadas. Cubriremos múltiples enfoques: Jenkins, ejecutores autoalojados de GitHub Actions, GitLab Runner y una canalización ligera de Bash, para que pueda elegir la opción que mejor se adapte a su stack y presupuesto.

Compartiré pasos, comandos y consejos de seguridad del mundo real a partir de más de 12 años de experiencia en la creación de pipelines para entornos de alojamiento web y de nube.


¿Qué es CI/CD en un servidor Linux?

La CI/CD (integración continua/entrega continua) automatiza la creación, prueba e implementación de aplicaciones. En un servidor Linux, esto implica usar un ejecutor u orquestador para extraer el código al realizar cambios, ejecutar pruebas, crear artefactos o contenedores e implementarlo de forma fiable en el entorno.

¿Qué es CI/CD en un servidor Linux?

Las herramientas principales incluyen Git, Docker, Jenkins, GitHub Actions, GitLab CI y Nginx.


¿Para quién es esto y qué construirás?

Este tutorial es ideal para desarrolladores, administradores de sistemas y equipos pequeños que desean una infraestructura segura y fácil de mantener. Canalización de CI / CD. Configurarás un servidor basado en Ubuntu/Debian, agregarás un agente de CI, configurarás pipelines y desplegarás una aplicación web en contenedores detrás. Nginx con reversión. También hablaremos de secretos, cortafuegos, registros y monitorización.

  • Servidor Linux (se recomienda Ubuntu 22.04+ o Debian 12)
  • Acceso root o sudo, SSH claves
  • Repositorio Git (GitHub, GitLab, Bitbucket)
  • Docker y Docker Compose (o entornos de ejecución de lenguaje como Node.js/Python/Java)
  • Dominio y DNS (opcional pero recomendado para HTTPS)

Consejo de hosting: Una instancia VPS o en la nube con 2–4 vCPU, 4–8 GB RAM Se adapta a la mayoría de las cargas de trabajo de CI/CD pequeñas. Si prefiere managed asistencia, YouStableAlojamiento VPS de y manageLos planes de servidor facilitan la implementación de CI/CD con imágenes pre-endurecidas, instantáneas y soporte 24×7.


Paso 1: Configuración del servidor base (la seguridad es lo primero)

Refuerce la seguridad del servidor antes de instalar las herramientas de CI. Utilice un usuario que no sea root. SSH llaves, un cortafuegos y paquetes esenciales.

# Create a non-root user
sudo adduser ci
sudo usermod -aG sudo,docker ci

# SSH hardening (on your local machine)
ssh-copy-id ci@your_server_ip

# Basic packages and updates
sudo apt update && sudo apt -y upgrade
sudo apt -y install git curl ufw fail2ban ca-certificates gnupg lsb-release

# Enable firewall
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable

# Install Docker (official repo)
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo 
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] 
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | 
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Allow ci user to run docker without sudo (re-login required)
sudo usermod -aG docker ci

Opcional: Instalar Nginx para enrutar su aplicación y terminar TLS con Vamos a cifrar.

sudo apt -y install nginx
sudo ufw allow "Nginx Full"

# Example minimal reverse proxy (adjust server_name and upstream)
sudo bash -c 'cat >/etc/nginx/sites-available/app.conf' <<EOF
server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
EOF
sudo ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/app.conf
sudo nginx -t && sudo systemctl reload nginx

Paso 2: Elija su arquitectura de CI/CD

  • Ejecutor autoalojado de GitHub Actions: Integración estrecha con GitHub, pipelines YAML, rápido para repositorios mono.
  • Ejecutor de GitLab: Funciona con GitLab CI/CD usando shell, Docker o ejecutores de Kubernetes.
  • Jenkins: Altamente extensible, rico en complementos, excelente para orquestación compleja de múltiples repositorios.
  • Bash ligero: Los equipos pequeños pueden crear, probar e implementar scripts activados por webhooks o cron.

Elija una de las siguientes rutas principales. Puede combinarlas (por ejemplo, Acciones para CI y Ansible para CD) a medida que escala.

Opción A: Ejecutor autoalojado de GitHub Actions

Ejecuta flujos de trabajo en tu propio servidor Linux para tener control total y la ubicación de la caché. Registra el ejecutor en la configuración de tu repositorio de GitHub > Acciones > Ejecutores.

# As ci user
mkdir -p ~/actions-runner && cd ~/actions-runner
# Download the latest runner from GitHub (replace version/URL from GitHub UI)
curl -o actions-runner.tar.gz -L https://github.com/actions/runner/releases/download/vX.Y.Z/actions-runner-linux-x64-X.Y.Z.tar.gz
tar xzf actions-runner.tar.gz

# Configure (use the token from GitHub Runner setup)
./config.sh --url https://github.com/your-org/your-repo --token YOUR_TOKEN --labels self-hosted,linux,prod

# Install as a service
sudo ./svc.sh install
sudo ./svc.sh start
sudo systemctl status actions.runner.*

Ejemplo de flujo de trabajo de GitHub Actions para compilar, probar, dockerizar e implementar con Docker Compose localmente en el servidor:

name: CI/CD
on:
  push:
    branches: [ "main" ]
jobs:
  build-test-deploy:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install deps & test
        run: |
          npm ci
          npm test --if-present

      - name: Build Docker image
        run: |
          docker build -t registry.example.com/myapp:${GITHUB_SHA::7} .
          docker tag registry.example.com/myapp:${GITHUB_SHA::7} registry.example.com/myapp:latest

      - name: Push image (if using private registry)
        env:
          REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
          REGISTRY_PASS: ${{ secrets.REGISTRY_PASS }}
        run: |
          echo "$REGISTRY_PASS" | docker login registry.example.com -u "$REGISTRY_USER" --password-stdin
          docker push registry.example.com/myapp:${GITHUB_SHA::7}
          docker push registry.example.com/myapp:latest

      - name: Deploy with Compose
        run: |
          docker compose pull || true
          docker compose up -d --remove-orphans
          docker image prune -f

Crea un docker-compose.yml mínimo en tu repositorio:

services:
  app:
    image: registry.example.com/myapp:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    env_file:
      - .env

Opción B: GitLab Runner en Linux

Usa GitLab CI/CD con un shell o un ejecutor de Docker. Registra tu ejecutor con un token de proyecto o grupo.

curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt -y install gitlab-runner

# Register runner (shell executor for simplicity)
sudo gitlab-runner register 
  --url https://gitlab.com/ 
  --registration-token YOUR_TOKEN 
  --executor shell 
  --description "linux-shell-runner"

Ejemplo .gitlab-ci.yml:

stages: [test, build, deploy]

variables:
  DOCKER_HOST: "unix:///var/run/docker.sock"

test:
  stage: test
  script:
    - npm ci
    - npm test --if-present

build:
  stage: build
  script:
    - docker build -t registry.example.com/myapp:$CI_COMMIT_SHORT_SHA .
    - docker tag registry.example.com/myapp:$CI_COMMIT_SHORT_SHA registry.example.com/myapp:latest
    - echo $REGISTRY_PASS | docker login registry.example.com -u $REGISTRY_USER --password-stdin
    - docker push registry.example.com/myapp:$CI_COMMIT_SHORT_SHA
    - docker push registry.example.com/myapp:latest
  only:
    - main

deploy:
  stage: deploy
  script:
    - docker compose pull
    - docker compose up -d --remove-orphans
    - docker image prune -f
  environment:
    name: production
  only:
    - main

Opción C: Jenkins Pipeline en Linux

Jenkins es una potencia para flujos de trabajo complejos y promoción en múltiples entornos.

# Install Java and Jenkins
sudo apt -y install openjdk-17-jre
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee 
  /usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] 
  https://pkg.jenkins.io/debian-stable binary/ | sudo tee 
  /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt update && sudo apt -y install jenkins
sudo systemctl enable --now jenkins
# Access: http://your_server_ip:8080 (retrieve initial admin password)

Ejemplo de Jenkinsfile (declarativo):

pipeline {
  agent any
  environment {
    REGISTRY = 'registry.example.com'
    IMAGE = 'myapp'
  }
  stages {
    stage('Checkout') {
      steps { checkout scm }
    }
    stage('Test') {
      steps {
        sh 'npm ci'
        sh 'npm test --if-present'
      }
    }
    stage('Build & Push Image') {
      steps {
        withCredentials([usernamePassword(credentialsId: 'registry-creds', usernameVariable: 'USER', passwordVariable: 'PASS')]) {
          sh '''
            echo "$PASS" | docker login $REGISTRY -u "$USER" --password-stdin
            TAG=$(git rev-parse --short HEAD)
            docker build -t $REGISTRY/$IMAGE:$TAG .
            docker tag $REGISTRY/$IMAGE:$TAG $REGISTRY/$IMAGE:latest
            docker push $REGISTRY/$IMAGE:$TAG
            docker push $REGISTRY/$IMAGE:latest
          '''
        }
      }
    }
    stage('Deploy') {
      steps {
        sh 'docker compose pull && docker compose up -d --remove-orphans'
      }
    }
  }
  post {
    always { sh 'docker image prune -f || true' }
  }
}

Opción D: CI/CD ligero de Bash (sin orquestador)

Para proyectos muy pequeños, use un gancho de Git post-recepción o un script activado por cron para compilar e implementar. Manténgalo simple pero seguro.

#!/usr/bin/env bash
set -euo pipefail

REPO_DIR=/opt/myapp
cd "$REPO_DIR"

echo "==> Pulling latest..."
git fetch --all
git checkout main
git pull --ff-only

echo "==> Running tests..."
npm ci
npm test --if-present

echo "==> Building & deploying..."
docker build -t myapp:latest .
docker compose up -d --build --remove-orphans
docker image prune -f

Secretos, variables de entorno y reversiones

  • Almacena secretos en la plataforma (secretos de GitHub, variables de integración continua de GitLab, credenciales de Jenkins). Nunca envíes archivos .env.
  • Utilice configuraciones específicas del entorno: .env.staging y .env.production con secretos seguros manager si es posible.
  • Etiquete las versiones (por ejemplo, versiones semánticas) y mantenga la versión anterior disponible para una rápida reversión con Docker Compose o un directorio de versiones con enlace simbólico.
  • Las implementaciones azul/verde o canarias reducen el riesgo de las aplicaciones de alto tráfico.

Lista de verificación para fortalecer la seguridad

  • Principio del mínimo privilegio: ejecutar runners con usuarios no root; limitar sudo.
  • Red: cerrar los puertos no utilizados con UFW; aislar las redes de compilación y producción si es posible.
  • SSH: Autenticación basada en clave, deshabilitar el inicio de sesión con contraseña, rotar las claves periódicamente.
  • Dependencias: Escanee imágenes con Trivy o Grype; fije las imágenes base y aplique parches con frecuencia.
  • Registros y alertas: habilitar fail2ban; enviar registros a un sistema central; monitorear los servicios del corredor.
  • Copias de seguridad e instantáneas: Automatice a través de su panel de hosting; pruebe y restaure mensualmente.

Solución de problemas y observabilidad

  • Consultar servicios: estado de systemctl jenkins, gitlab runner o actions.runner.*
  • Registros de corredores: journalctl -u “acciones.runner*” -e, journalctl -u gitlab-runner -e
  • Registros de Docker: docker ps, registros de docker , eventos de Docker
  • Nginx: sudo tail -f /var/log/nginx/access.log /var/log/nginx/error.log
  • Fallos comunes: variables de entorno faltantes, credenciales de registro incorrectas, firewall que bloquea el registro saliente o los espejos de paquetes.

Consideraciones de costo y escalabilidad

  • Comience con 2–4 vCPU, 4–8 GB RAM; agregar CPU para construcciones y RAM para capas de Docker.
  • Utilice cachés de compilación y ejecutores anclados al servidor que aloja su registro de contenedores para mayor velocidad.
  • Separe las cargas de trabajo de CI de las de producción a medida que crece para evitar la contención de recursos.
  • Si necesita un rendimiento predecible, considere varios corredores y un registro dedicado.

Ejemplo de extremo a extremo: desde el envío hasta la producción

  • El desarrollador envía al servidor principal; CI extrae el código.
  • Ejecutar pruebas unitarias y linting.
  • Cree una imagen de Docker, etiquétela con SHA de confirmación y la última versión.
  • Insertar en el registro y actualizar Docker Compose en el servidor.
  • Compose recrea el contenedor con un tiempo de inactividad mínimo o nulo.
  • El punto final de verificación de estado confirma el éxito y se activan alertas en caso de fallas.

Este flujo es resistente, auditable y fácil de replicar para entornos de prueba y producción con diferentes variables y DNS Records.

Mejores prácticas para mantener su CI/CD saludable

  • Mantenga las tuberías rápidas: Dependencias de caché y pruebas paralelizadas.
  • Hacer que los fracasos sean ruidosos: fallar rápidamente, notificar a Slack/correo electrónico e incluir registros.
  • Artefactos inmutables: Construir una vez, promover a través de entornos con la misma imagen.
  • Despliegues idempotentes: Ejecutar "deploy" dos veces no debería dañar su aplicación.
  • Documente todo: README, libros de ejecución, pasos de reversión.

Preguntas Frecuentes

¿Cómo elijo entre Jenkins, GitHub Actions y GitLab CI?

Usa GitHub Actions si tu código reside en GitHub y deseas flujos de trabajo YAML sencillos. Elige GitLab CI para repositorios de GitLab integrados y ejecutores a nivel de grupo. Elige Jenkins para pipelines altamente personalizados, aprobaciones complejas o cuando necesites compatibilidad completa con plugins y orquestación multirepositorio.

¿Es necesario Docker para CI/CD en Linux?

No, pero Docker simplifica las compilaciones e implementaciones reproducibles. Sin Docker, se pueden ejecutar compilaciones nativas del lenguaje (Node, Python, Java) e implementar mediante servicios rsync o systemd. Para mayor consistencia y portabilidad, se recomienda encarecidamente el uso de contenedores.

¿Cómo puedo proteger los secretos en mi pipeline?

Almacene los secretos en su plataforma de integración continua (secretos de GitHub, variables de GitLab, credenciales de Jenkins). Evite archivos .env de texto plano en los repositorios. Para configuraciones avanzadas, considere HashiCorp Vault o KMS en la nube. Limite quién puede leer los secretos y rótelos regularmente.

¿Cuál es la forma más sencilla de revertir una implementación incorrecta?

Conserve la etiqueta de imagen de Docker anterior y restaure docker compose.yaml a esa etiqueta. Luego, ejecute docker compose up -d. Si utiliza implementaciones sin contenedores, mantenga una versión "actual" con enlace simbólico y vuelva a cambiarla. A continuación, reinicie el servicio.

¿Puedo ejecutar CI/CD en un VPS pequeño?

Sí. Para proyectos pequeños, un 2 vCPU/ 4 GB RAM Un VPS es suficiente. Utilice el almacenamiento en caché y evite compilaciones paralelas pesadas. A medida que sus pipelines crezcan, aumente los recursos o separe los ejecutores de CI de las cargas de trabajo de producción. Proveedores como YouStable Hacer que el escalado vertical y horizontal sea sencillo.

Deja Tu Comentario

Su dirección de correo electrónico no será publicada. Las areas obligatorias están marcadas como requeridas *

Ir al Inicio