Contenerización de aplicaciones Swift con Docker: guía completa para desarrolladores

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Por qué Swift y Docker son la pareja ideal para el desarrollo backend

\n\n

Si está acostumbrado a pensar que Swift es solo desarrollo móvil para iOS, es hora de sorprenderse. Swift avanza con paso firme hacia el lado del servidor: Vapor, Kitura, Perfect — frameworks que permiten escribir backends rápidos y seguros. Pero hay un problema: ¿cómo garantizar que su aplicación funcione igual en la Mac del desarrollador y en el servidor de producción con Ubuntu?

\n\n

La respuesta es la contenerización de aplicaciones Swift con Docker. Docker permite empaquetar todo: el binario en sí, las bibliotecas del sistema, las dependencias de Swift Package Manager (SPM) — y ejecutarlo en cualquier lugar. Nada de «en mi máquina funciona» y «en la tuya no».

\n\n

En este artículo, veremos cómo compilar una aplicación Swift en una imagen Docker, optimizar su tamaño, configurar una compilación de múltiples etapas e incluso agregar recarga en caliente para el desarrollo. ¡Allá vamos!

\n\n

Paso 1. Preparación de la aplicación Swift

\n\n

Como ejemplo, tomaremos una aplicación web mínima con Vapor. Si aún no tiene un proyecto, créelo:

\n\n
mkdir MySwiftApp && cd MySwiftApp\nswift package init --type executable
\n\n

Añadimos Vapor en Package.swift:

\n\n
// swift-tools-version:5.7\nimport PackageDescription\n\nlet package = Package(\n    name: "MySwiftApp",\n    dependencies: [\n        .package(url: "https://github.com/vapor/vapor.git", from: "4.89.0")\n    ],\n    targets: [\n        .executableTarget(\n            name: "MySwiftApp",\n            dependencies: [\n                .product(name: "Vapor", package: "vapor")\n            ]\n        )\n    ]\n)
\n\n

El main.swift más simple:

\n\n
import Vapor\n\nvar env = try Environment.detect()\ntry LoggingSystem.bootstrap(from: &env)\nlet app = Application(env)\ndefer { app.shutdown() }\n\napp.get("hello") { req -> String in\n    return "Hello from Swift in Docker!"\n}\n\ntry app.run()
\n\n

Verifique que el proyecto compile localmente: swift build. Si todo está bien, pasamos a la contenerización.

\n\n

Paso 2. Escribir el Dockerfile para Swift

\n\n

El secreto principal de una buena contenerización de Swift es la compilación de múltiples etapas. En la primera etapa, compilamos el binario; en la segunda, copiamos solo el binario y las dependencias de tiempo de ejecución. La imagen final resulta ser de 5 a 10 veces más pequeña.

\n\n
# ---- Etapa 1: Compilación ----\nFROM swift:5.9-jammy AS build\n\nWORKDIR /app\n\n# Copiamos Package.swift y Package.resolved para cachear las dependencias\nCOPY Package.swift ./\nCOPY Package.resolved ./\n\n# Descargamos las dependencias por separado — esto se cachea con Docker\nRUN swift package resolve\n\n# Copiamos el código fuente\nCOPY Sources ./Sources\n\n# Compilación en modo release\nRUN swift build -c release --static-swift-stdlib\n\n# ---- Etapa 2: Runtime ----\nFROM ubuntu:jammy AS runtime\n\n# Instalamos las dependencias mínimas para el runtime de Swift\nRUN apt-get update && apt-get install -y \\\n    libicu70 \\\n    libcurl4 \\\n    libxml2 \\\n    && rm -rf /var/lib/apt/lists/*\n\nWORKDIR /app\n\n# Copiamos solo el binario desde la etapa de compilación\nCOPY --from=build /app/.build/release/MySwiftApp .\n\n# Puerto que Vapor escucha por defecto\nEXPOSE 8080\n\nCMD ["./MySwiftApp"]
\n\n

Puntos clave:

\n
    \n
  • --static-swift-stdlib — enlace estático de la biblioteca estándar, para no arrastrar libswiftCore.so en tiempo de ejecución.
  • \n
  • Separación de COPY — primero Package.swift, luego el código. Así Docker usa la caché de capas y no recompila las dependencias al cambiar el código fuente.
  • \n
  • La imagen base ubuntu:jammy pesa ~80 MB, la imagen final pesa alrededor de 100-150 MB.
  • \n
\n\n

Paso 3. Compilación y ejecución del contenedor

\n\n

Compilamos la imagen:

\n\n
docker build -t my-swift-app .
\n\n

Ejecutamos:

\n\n
docker run -p 8080:8080 my-swift-app
\n\n

O

Blogs

Book Recommendations