¿Dónde se ejecuta realmente el despliegue?

 Exactamente! Has dado en el clavo. No, no necesitas tener Git instalado dentro del contenedor. De hecho, no deberías tenerlo.

Vamos a desglosarlo para que quede completamente claro y veas por qué es así.


¿Dónde se ejecuta realmente el despliegue?

Cuando hablamos de "subir tu aplicación por Git" (en lugar de FTP), el proceso NO ocurre dentro del contenedor de tu aplicación (PHP-FPM). Ocurre en el servidor anfitrión (host) o en un servidor de despliegue separado.

Escenario típico de despliegue con Git

Imagina que tienes un servidor en la nube (DigitalOcean, AWS, etc.) con esta estructura:

text
Servidor de Producción
├── Host (Sistema Operativo: Linux)
│   ├── Git (¡Instalado aquí!)
│   ├── Código de la aplicación (en /var/www/mi-app)
│   ├── Docker
│   │   ├── Contenedor PHP-FPM  (NO tiene Git)
│   │   ├── Contenedor Nginx    (NO tiene Git)
│   │   └── Contenedor MySQL    (NO tiene Git)
│   └── Scripts de despliegue
└── (Usuarios finales acceden vía HTTP)

¿Cómo funciona el despliegue con Git en este escenario?

  1. Haces git push desde tu computadora local a GitHub (o GitLab, Bitbucket).

  2. El servidor de producción (el host) tiene Git instalado y detecta el nuevo commit.

  3. El servidor ejecuta git pull en el host, no en el contenedor. Los archivos se actualizan en /var/www/mi-app.

  4. El servidor ejecuta comandos de construcción y actualización en el host:

    bash
    # En el host, NO dentro del contenedor
    docker compose exec app composer install   # Actualiza dependencias dentro del contenedor
    docker compose exec app php artisan migrate # Ejecuta migraciones dentro del contenedor
    docker compose restart                     # Reinicia servicios si es necesario
  5. Gracias a los volúmenes, los archivos actualizados en el host (/var/www/mi-app) se montan automáticamente dentro del contenedor (en /var/www/html). El contenedor ahora ejecuta la nueva versión sin necesidad de saber que existe Git.


¿Por qué no instalar Git en el contenedor?

RazónExplicación
Responsabilidad únicaUn contenedor debe hacer una sola cosa: ejecutar tu aplicación PHP. Git es una herramienta de control de versiones, no un runtime de aplicación.
Tamaño y complejidadInstalar Git añade peso innecesario a tu imagen Docker.
SeguridadEl contenedor no necesita credenciales, claves SSH o acceso a tu repositorio remoto. Si el contenedor es comprometido, no tendrá acceso a tu código fuente en GitHub.
PersistenciaLos contenedores son efímeros (se crean y destruyen constantemente). Un docker compose down -v eliminaría cualquier cambio hecho dentro del contenedor.
Flujo de trabajo correctogit pull descarga archivos. Si lo ejecutas dentro del contenedor, esos archivos se escribirían en el sistema de archivos del contenedor, que es volátil y no se sincroniza correctamente con el host.

El ejemplo correcto: Despliegue con Git (sin FTP)

Herramienta: Deployer (PHP)

bash
# 1. En tu computadora local, haces push a GitHub
git push origin main

# 2. En tu servidor (host), ejecutas el script de despliegue
# (Esto se puede automatizar con GitHub Actions, GitLab CI, etc.)

Script de despliegue simple (en el host):

bash
#!/bin/bash
# deploy.sh - Se ejecuta en el HOST, no en el contenedor

# 1. Actualizar código desde GitHub (Git está en el host)
cd /var/www/mi-app
git pull origin main

# 2. Instalar dependencias dentro del contenedor
docker compose exec app composer install --no-dev --optimize-autoloader

# 3. Ejecutar migraciones dentro del contenedor
docker compose exec app php artisan migrate --force

# 4. Limpiar caché dentro del contenedor
docker compose exec app php artisan config:cache
docker compose exec app php artisan route:cache
docker compose exec app php artisan view:cache

# 5. Reiniciar servicios (opcional)
docker compose restart

echo "¡Despliegue completado!"

Herramienta: GitHub Actions (CI/CD)

yaml
name: Deploy to Production

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to Server
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            # Estos comandos se ejecutan en el HOST del servidor
            cd /var/www/mi-app
            git pull origin main
            docker compose exec app composer install --no-dev --optimize-autoloader
            docker compose exec app php artisan migrate --force
            docker compose exec app php artisan config:cache

En este flujo:

  • ✅ El Git se ejecuta en el host (git pull origin main)

  • ✅ Los comandos de construcción se ejecutan en el host (docker compose exec)

  • ✅ El contenedor solo ejecuta el código actualizado (sin saber nada de Git)


El error común que debes evitar

dockerfile
# ❌ NO hagas esto en tu Dockerfile
FROM php:8.2-fpm
RUN apt-get update && apt-get install -y git   # ¡NO!
RUN git clone https://github.com/mi-app.git .  # ¡NO!

Si haces esto, tu contenedor:

  • Será más grande y pesado

  • Tendrá credenciales expuestas (si usas autenticación)

  • No podrá actualizarse fácilmente (cada cambio requiere reconstruir la imagen)

  • No podrá usar volúmenes correctamente (el código estaría dentro del contenedor, no en el host)


Resumen final

¿Qué necesito?¿Dónde va?¿Por qué?
Git (para control de versiones)En el HOST (tu máquina local o servidor)Es donde se ejecutan git init, git add, git commit, git push, git pull
Código de la aplicaciónEn el HOST (sincronizado con el contenedor vía volúmenes)Los archivos deben persistir y ser editables desde el host
Contenedor DockerEn el HOST (ejecuta la aplicación)Solo debe contener lo necesario para ejecutar tu app (PHP, Nginx, MySQL)
Git dentro del contenedor❌ NONo es necesario. El contenedor solo ejecuta el código que ya está sincronizado


gh

 Así que ya lo sabes! Git vive en el host, no en el contenedor. El contenedor es un "actor" pasivo que ejecuta el código que el host le proporciona a través de los volúmenes. El host es el "director" que orquesta todo: descarga el código con Git, lo actualiza, ejecuta migraciones y reinicia servicios.

¡Felicidades! 🎉 Ahora entiendes perfectamente la separación de responsabilidades y por qué no necesitas Git dentro del contenedor

Comentarios

Entradas más populares de este blog

11-intro

12. Exposición sobre los comandos usados hasta el momento

13. Cambiar nombre de la rama Master a Main