Container — an isolated, reproducible process environment (Docker)
Concept
Container — a lightweight, isolated process that packages an application and its dependencies (code, runtime, libraries, config) into a single unit. Containers run the same way on any machine that has the container engine.
Not a virtual machine: A VM virtualizes hardware and runs a full OS. A container shares the host OS kernel but isolates the process. Containers are much lighter (start in milliseconds, use MB of memory vs GB for VMs).
Docker: The dominant container platform. docker run, docker build, Dockerfile.
Dockerfile: Instructions for building a container image. Layered — each instruction adds a layer. Layers are cached.
What a container solves:
- "Works on my machine" — if it works in the container, it works everywhere.
- Dependency isolation — PHP 8.4 for one app, PHP 8.1 for another, no conflict.
- Reproducible environments — same container in dev, CI, and production.
- Fast setup —
docker-compose upstarts the entire stack (app + DB + Redis) in one command.
Container lifecycle: Build (from Dockerfile) → Run (container executes) → Stop → Remove. Containers are ephemeral: stopping one destroys its state. Persistent data goes in volumes.
Docker Compose: Tool for running multi-container applications. docker-compose.yml defines services (app, mysql, redis), networks, volumes. docker-compose up -d starts everything.
Orchestration: Managing many containers at scale. Kubernetes (K8s) is the industry standard. Laravel Forge, Envoyer, Vapor for PHP-specific deployment.
Code Example
# Dockerfile for a Laravel application
FROM php:8.4-fpm-alpine
# Install system dependencies
RUN apk add --no-cache \
libpng-dev \
libzip-dev \
nodejs \
npm
# Install PHP extensions
RUN docker-php-ext-install pdo pdo_mysql zip gd opcache pcntl
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www
# Copy composer files first (for layer caching)
COPY composer.json composer.lock ./
RUN composer install --no-interaction --no-dev --optimize-autoloader
# Copy application code
COPY . .
# Build assets
RUN npm ci && npm run build
# Set file permissions
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]# docker-compose.yml — local development stack
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/var/www # mount source for live reload in dev
depends_on:
- mysql
- redis
environment:
APP_ENV: local
DB_HOST: mysql
REDIS_HOST: redis
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- .:/var/www
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: zira
MYSQL_ROOT_PASSWORD: secret
volumes:
- mysql_data:/var/lib/mysql # persist data across container restarts
ports:
- "3306:3306"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
mysql_data:# Common Docker commands
docker-compose up -d # start all services in background
docker-compose exec app bash # shell into app container
docker-compose exec app php artisan migrate
docker-compose logs -f app # tail logs
docker-compose down # stop and remove containers