Docker and Swift: Containerizing Applications from A to Z

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Docker and Swift Are the Perfect Pair for Modern Development

The world of iOS and macOS development has long been associated exclusively with Xcode and local builds. However, with the advent of server-side Swift (especially the Vapor framework) and the growing popularity of microservice architecture, containerization has become not just a trend, but a necessity. Docker for a Swift developer is not only about environment isolation, but also about build consistency, simplified CI/CD, and easy deployment to any server.

In this article, we will cover the full cycle of working with Docker and Swift: from writing a simple Dockerfile for macOS/Linux to deploying a full-fledged web application on Vapor. You will learn how to avoid common mistakes and make your containers lightweight and secure.



Main Part: Step-by-Step Guide to Containerizing Swift



1. Basics: Dockerfile for a Swift Application (macOS vs Linux)

The first thing to understand: Swift is a cross-platform language, but Docker traditionally works on Linux containers. For macOS development, you can use images with a Linux build of Swift (e.g., swift:5.9-focal) or, if the macOS environment is critical for you, use virtualization (Docker Desktop for Mac). However, for server applications (Vapor, Kitura), Linux images are the standard.

Basic Dockerfile for a server-side Swift application (Vapor):

# Use the official Swift imageFROM swift:5.9-focal AS build

# Set the working directoryWORKDIR /app

# Copy Package.swift and Package.resolved files for caching dependenciesCOPY Package.swift Package.resolved ./RUN swift package resolve

# Copy the source codeCOPY Sources ./SourcesRUN swift build -c release

# Final image (minimal)FROM ubuntu:focalWORKDIR /appCOPY --from=build /app/.build/release /appEXPOSE 8080CMD ["./Run"]

This approach uses a multi-stage build: the first stage compiles the application, the second creates a minimal image containing only the binary and necessary libraries. The final image weighs ~60-80 MB instead of 2 GB.



2. Image Optimization: Caching and Dependencies

Swift is a compiled language, and each build can take minutes. To speed up the process, use Docker layer caching. The key technique: first copy Package.swift and Package.resolved, then run swift package resolve, and only then copy the source files. This ensures that dependencies are rebuilt only when Package.swift changes, not with every code change.

Additional optimization — using .dockerignore:

.git.gitignore.build*.xcworkspace*.xcodeprojDerivedDataPackagesREADME.mdTests

This prevents unnecessary files (tests, git, Xcode projects) from entering the build context, which speeds up context transfer and reduces image size.



3. Docker Compose: Linking Swift with a Database and Cache

Real applications rarely live in isolation. For a typical Vapor backend, you will need PostgreSQL (or Fluent), Redis for caching, and possibly Nginx. docker-compose.yml allows you to run everything with a single command.

Example docker-compose.yml for a Swift application with PostgreSQL and Redis:

version: '3.8'services:  app:    build: .    ports:      - "8080:8080"    environment:      - DATABASE_HOST=db      - DATABASE_PORT=5432      - REDIS_HOST=redis      - REDIS_PORT=6379    depends_on:      - db      - redis    restart: unless-stopped

db: image: postgres:15-alpine environment: POSTGRES_DB: myapp POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432"

redis: image:

Blogs

Book Recommendations