FEATURED: Best Server Hosts in Europe 2026: The Ultimate Guide
A lot has evolved since I shared my top Docker picks in 2025. I’ve streamlined the whole setup, cut the noise, and focused on what I actually use — locally and externally. Better organised, better documented, and somehow more enjoyable than ever. Could not stick to 10, so its 10++++!
Note: New to the mix -> Resilio Sync.
Why Self-Host with Docker in 2026?
Before diving into the list, let’s talk about why running your own stack with Docker is having such a moment right now:
- Control & Privacy: Your data lives on your server, not in a datacenter owned by a company that can change its terms whenever it feels like it
- Kill the Subscription: One-time setup beats monthly SaaS bills that compound year after year — host a dozen apps for less than the price of a single mid-tier subscription
- True Customization: Tweak configs, replace components, extend functionality — you own the stack end to end
- Data Sovereignty: GDPR-compliant by default, no foreign jurisdiction to worry about, no third-party data agreements to read through
- Avoid Vendor Lock-in: Migrate freely, export anything, no hostage data — if a project goes commercial or dies, you just swap the container
- Learn by Doing: Running Docker Compose stacks is one of the fastest ways to actually understand how modern infrastructure works
- Cost at Scale: Once you’ve got a server running, adding a new service is literally a few lines of YAML
My Top Universal Docker Solutions
These run well in almost any environment and serve as the backbone of a solid self-hosted setup.
1. Nginx Proxy Manager – Visual Reverse Proxy Management
Nginx Proxy Manager provides a clean web interface for managing Nginx reverse proxy hosts, SSL certificates, and redirects – without touching a config file. A practical alternative to manually maintaining Nginx or Traefik configurations.
Features
- Web UI for managing proxy hosts, redirects, and 404 hosts
- Automatic Let’s Encrypt SSL certificate provisioning and renewal
- Access lists and basic HTTP authentication per host
- Custom Nginx configuration snippets per proxy host
Docker Deployment
docker run -d -p 80:80 -p 81:81 -p 443:443 \
-e DB_SQLITE_FILE=/data/database.sqlite \
-v npm_data:/data \
-v npm_letsencrypt:/etc/letsencrypt \
jc21/nginx-proxy-manager
2. Portainer – Simplified Docker Management
Portainer provides a user-friendly web interface for managing Docker containers, images, and volumes. Using it locally and externally.
Features
- Web-based UI for container management
- Supports Docker Swarm and Kubernetes
- Role-based access control
- Application deployment templates
Docker Deployment
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer-ce
3. BookStack – Self-Hosted Wiki and Documentation
BookStack is an open-source platform for organizing and storing information in a structured, book-like hierarchy. Ideal for internal documentation and knowledge bases.
Features
- Hierarchical organization with Shelves, Books, Chapters, and Pages
- Built-in WYSIWYG and Markdown editor
- Full-text search across all content
- Role-based permissions and LDAP/SAML support
Docker Deployment
docker run -d -p 8080:80 \
-e APP_URL=http://localhost:8080 \
-e DB_HOST=your_db_host \
-e DB_DATABASE=bookstack \
-e DB_USERNAME=bookstack \
-e DB_PASSWORD=your_password \
solidnerd/bookstack
4. n8n – Self-Hosted Workflow Automation
n8n is a powerful, self-hosted workflow automation tool that connects apps, APIs, and services through a visual node-based editor. A flexible alternative to Zapier or Make with full data ownership.
Features
- Visual drag-and-drop workflow builder with 400+ integrations
- Supports custom JavaScript and Python code nodes
- Webhook triggers, cron scheduling, and event-based automation
- Self-hosted with optional queue mode via Redis and PostgreSQL
Docker Deployment
docker run -d -p 5678:5678 \
-e N8N_BASIC_AUTH_ACTIVE=true \
-e N8N_BASIC_AUTH_USER=admin \
-e N8N_BASIC_AUTH_PASSWORD=your_password \
-v n8n_data:/home/node/.n8n \
n8nio/n8n
5. Kopia – Fast and Secure Backup Tool
Kopia is an open-source backup and restore tool with client-side encryption, deduplication, and compression. A modern alternative to tools like Duplicati or Restic, offering both a CLI and a web UI for managing backup policies and snapshot repositories.
Features
- Client-side end-to-end encryption with multiple cipher options
- Content-addressable deduplication for efficient storage usage
- Supports local, SFTP, S3-compatible, Google Drive, and rclone backends
- Web UI and CLI interface with scheduled snapshot policies
Docker Deployment
docker run -d -p 51515:51515 \
-e KOPIA_PASSWORD=your_repository_password \
-v kopia_config:/app/config \
-v kopia_cache:/app/cache \
-v /path/to/backup/source:/data:ro \
-v /path/to/repository:/repository \
kopia/kopia server start \
--insecure --address=0.0.0.0:51515
6. Monocker – Minimal Docker Container Status Notifications
Monocker is a lightweight, self-hosted Docker container monitoring tool that sends notifications whenever a container changes state. A no-frills solution for staying informed about container crashes or unexpected stops without the overhead of a full monitoring stack.
Features
- Monitors all running containers for state changes in real time
- Supports Telegram, Slack, Pushover, ntfy, and other notification channels
- Per-container include/exclude filtering via labels or environment variables
- Minimal footprint – single container with no external dependencies
Docker Deployment
docker run -d \
--name monocker \
-v /var/run/docker.sock:/var/run/docker.sock \
-e SERVER_LABEL=my-server \
-e NOTIFICATION_TYPE=ntfy \
-e NTFY_URL=http://your_ntfy_host/topic \
petersem/monocker
7. Duplicati – Self-Hosted Encrypted Cloud Backup
Duplicati is a free, open-source backup client with a web-based interface for scheduling encrypted, incremental backups to a wide range of local and cloud storage destinations. A reliable set-and-forget backup solution for self-hosted environments that prioritizes simplicity without sacrificing security.
Features
- AES-256 client-side encryption before data leaves the machine
- Incremental backups with deduplication to minimize storage usage
- Supports S3, Backblaze B2, FTP, SFTP, WebDAV, and 30+ backends
- Web UI with scheduling, retention policies, and email notifications
Docker Deployment
docker run -d -p 8200:8200 \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/Berlin \
-v duplicati_config:/config \
-v duplicati_backups:/backups \
-v /path/to/source:/source:ro \
lscr.io/linuxserver/duplicati
My Top Local Docker Solutions
1. Plex – Media Streaming Done Right
Plex enables you to create your own Netflix-like experience by organizing and streaming your media collection.
Features
- Remote access to your media
- Automatic media organization and metadata fetching
- Support for multiple users and devices
- Integration with streaming services
Docker Deployment
docker run -d --name=plex -p 32400:32400 -v plex_data:/config -e PLEX_CLAIM=claim-token plexinc/pms-docker
2. TimeTagger – Self-Hosted Time Tracking
TimeTagger is an open-source, self-hosted time tracking tool with a visual timeline interface. Designed for freelancers and developers who want a lightweight alternative to commercial time tracking services with full data ownership.
Features
- Interactive visual timeline for logging and reviewing time entries
- Tag-based organization with nested tag support
- Reporting and export for invoicing and analysis
- REST API for integration with external tools and automation
Docker Deployment
docker run -d -p 80:80 \
-e TIMETAGGER_BIND=0.0.0.0:80 \
-v timetagger_data:/root/_timetagger \
ghcr.io/almarklein/timetagger
3. Firefly III – Self-Hosted Personal Finance Manager
Firefly III is a feature-rich, self-hosted personal finance manager for tracking income, expenses, budgets, and accounts. A privacy-first alternative to cloud-based tools like YNAB or Mint, with full control over your financial data.
Features
- Multi-account tracking with support for assets, liabilities, and cash
- Budget management, bill tracking, and recurring transaction rules
- Detailed reports and charts for income, expenses, and net worth
- REST API and Data Importer tool for automated bank transaction imports
Docker Deployment
docker run -d -p 8080:8080 \
-e APP_KEY=your_32_char_app_key \
-e APP_URL=http://localhost:8080 \
-e DB_HOST=your_db_host \
-e DB_DATABASE=firefly \
-e DB_USERNAME=firefly \
-e DB_PASSWORD=your_password \
-v firefly_upload:/var/www/html/storage/upload \
fireflyiii/core
4. Homebox – Self-Hosted Home Inventory Management
Homebox is a lightweight, self-hosted inventory and organization system designed for tracking household items, assets, and warranties. A practical tool for home labs and households who want a structured, searchable record of their belongings without relying on spreadsheets or cloud services.
Features
- Item tracking with locations, labels, and custom fields
- Warranty and purchase tracking with expiry reminders
- QR code generation for physical labeling of items and locations
- CSV import/export and REST API for data portability
Docker Deployment
docker run -d -p 3100:7745 \
-e HBOX_LOG_LEVEL=info \
-e HBOX_WEB_MAX_UPLOAD_SIZE=10 \
-v homebox_data:/data \
ghcr.io/hay-kot/homebox
5. Mealie – Self-Hosted Recipe Manager and Meal Planner
Mealie is a self-hosted recipe management and meal planning application with automatic recipe scraping from any URL. A clean, family-friendly alternative to bookmarking recipes across multiple sites, with full control over your culinary data.
Features
- One-click recipe import by scraping any recipe URL automatically
- Meal planning calendar with drag-and-drop weekly schedule
- Shopping list generation from meal plans and individual recipes
- Multi-user support with household groups and REST API access
Docker Deployment
docker run -d -p 9925:9000 \
-e ALLOW_SIGNUP=true \
-e BASE_URL=http://localhost:9925 \
-v mealie_data:/app/data \
ghcr.io/mealie-recipes/mealie
6. Paperless-ngx – Self-Hosted Document Management
Paperless-ngx is a self-hosted document management system that ingests, indexes, and archives scanned documents and PDFs. A community-maintained successor to the original Paperless project, turning a pile of physical and digital paperwork into a fully searchable, tagged document archive.
Features
- Automatic OCR for scanned documents with full-text search
- Tag, correspondent, and document type classification with auto-matching rules
- Multi-user support with fine-grained permissions per document
- REST API and email ingestion for automated document workflows
Docker Deployment
docker run -d -p 8000:8000 \
-e PAPERLESS_REDIS=redis://your_redis_host:6379 \
-e PAPERLESS_DBHOST=your_db_host \
-e PAPERLESS_SECRET_KEY=your_secret_key \
-e PAPERLESS_TIME_ZONE=Europe/Berlin \
-v paperless_data:/usr/src/paperless/data \
-v paperless_media:/usr/src/paperless/media \
-v paperless_consume:/usr/src/paperless/consume \
ghcr.io/paperless-ngx/paperless-ngx
7. Dashy – Self-Hosted Personal Dashboard
Dashy is a highly customizable, self-hosted start page and personal dashboard for organizing links, services, and widgets in one place. A polished home lab hub for quick access to all self-hosted tools and external services from a single browser tab.
Features
- Fully customizable layout with sections, icons, and themes
- Built-in status monitoring with live uptime indicators per service
- Widgets for weather, RSS feeds, system stats, and more
- YAML-based configuration with optional authentication and multi-user support
Docker Deployment
docker run -d -p 4000:80 \
-v dashy_config:/app/user-data \
lissy93/dashy
My Top External Docker Solutions
1. Nextcloud – Your Own Cloud Storage
If you need an alternative to Google Drive or Dropbox, Nextcloud is the best self-hosted solution. It allows you to store files, share documents, and even integrate calendar and email functions.
Features
- File synchronization and sharing
- Calendar and contacts integration
- Built-in office suite (Collabora or OnlyOffice)
- End-to-end encryption
Docker Deployment
docker run -d -p 8080:80 --name nextcloud -v nextcloud_data:/var/www/html nextcloud
2. Bugsink – Self-Hosted Error Tracking
Bugsink is a lightweight, self-hosted error tracking platform compatible with the Sentry SDK. Designed for teams who want full control over their error data without external dependencies.
Features
- Sentry SDK compatible – no client-side changes required
- Supports Python, JavaScript, PHP, and more
- Issue grouping, deduplication, and event history
- Minimal dependencies – runs as a single Docker container
Docker Deployment
docker run -d -p 8000:8000 \
-e SECRET_KEY=your_secret_key \
-v bugsink_data:/var/lib/bugsink \
bugsink/bugsink
3. ntfy – Self-Hosted Push Notifications
ntfy is a simple, self-hosted pub/sub notification service that sends push notifications to your phone or desktop via HTTP. No account or API key required – just publish to a topic and subscribe.
Features
- HTTP-based publish/subscribe for instant push notifications
- Native Android and iOS apps with background delivery
- Supports priority levels, tags, icons, and action buttons
- Easy integration with bash scripts, cron jobs, and monitoring tools
Docker Deployment
docker run -d -p 8080:80 \
-v ntfy_data:/var/lib/ntfy \
-v /etc/ntfy/server.yml:/etc/ntfy/server.yml \
binwiederhier/ntfy serve
4. Matomo – Self-Hosted Web Analytics
Matomo is a fully featured, self-hosted web analytics platform and the most widely used open-source alternative to Google Analytics. Full data ownership with GDPR compliance built in.
Features
- Comprehensive visitor tracking, heatmaps, and funnel analysis
- GDPR, CCPA, and ePrivacy compliant out of the box
- No data sampling – full unfiltered access to raw analytics
- Plugin ecosystem with tag manager, A/B testing, and SEO tools
Docker Deployment
docker run -d -p 8080:80 \
-e MATOMO_DATABASE_HOST=your_db_host \
-e MATOMO_DATABASE_DBNAME=matomo \
-e MATOMO_DATABASE_USERNAME=matomo \
-e MATOMO_DATABASE_PASSWORD=your_password \
-v matomo_data:/var/www/html \
matomo
5. Mosparo – Self-Hosted Spam Protection
Mosparo is an open-source, self-hosted spam protection solution for web forms. A privacy-friendly alternative to reCAPTCHA and hCaptcha that works without tracking, cookies, or sending data to third-party servers.
Features
- GDPR-compliant spam filtering without third-party dependencies
- Invisible honeypot and behavioral analysis – no CAPTCHA challenges
- WordPress, Typo3, and framework integrations via official plugins
- Customizable rulesets and submission log with detailed statistics
Docker Deployment
docker run -d -p 8080:80 \
-e MOSPARO_DB_HOST=your_db_host \
-e MOSPARO_DB_NAME=mosparo \
-e MOSPARO_DB_USER=mosparo \
-e MOSPARO_DB_PASSWORD=your_password \
-v mosparo_data:/var/www/html/var \
mosparo/mosparo
6. Uptime Kuma – Self-Hosted Uptime Monitoring
Uptime Kuma is a lightweight, self-hosted monitoring tool for tracking the availability of websites, services, and APIs. A polished alternative to services like UptimeRobot with a real-time dashboard and extensive notification support.
Features
- Monitors HTTP, TCP, DNS, Docker containers, and more
- Real-time dashboard with response time graphs and status history
- 90+ notification integrations including ntfy, Slack, and Telegram
- Public status pages with custom domains and branding
Docker Deployment
docker run -d -p 3001:3001 \
-v uptime-kuma_data:/app/data \
louislam/uptime-kuma
7. Rocket.Chat – Self-Hosted Team Messaging
Rocket.Chat is a feature-rich, self-hosted team communication platform with channels, direct messaging, video conferencing, and an extensible app engine. A robust open-source alternative to Slack or Microsoft Teams with full data sovereignty.
Features
- Channels, threads, direct messages, and video/audio conferencing
- Extensible Apps Engine for custom bots and integrations
- Omnichannel support for live chat, email, and social messaging
- LDAP, SAML, and OAuth authentication support
Docker Deployment
docker run -d -p 3000:3000 \
-e MONGO_URL=mongodb://your_mongo_host:27017/rocketchat \
-e ROOT_URL=http://localhost:3000 \
-e PORT=3000 \
-v rocketchat_uploads:/app/uploads \
rocket.chat
8. VDO.Ninja – Self-Hosted Browser-Based Video Streaming
VDO.Ninja is a free, open-source tool that uses WebRTC to bring remote camera feeds directly into OBS or any browser – with zero latency and no dedicated software required on the sender’s side. Fully self-hostable for complete control over the signaling infrastructure.
Features
- Browser-to-browser WebRTC video with near-zero latency
- Direct OBS integration via Browser Source – no capture card needed
- Supports multi-guest rooms, screen sharing, and audio mixing
- Self-hostable signaling server and TURN relay for full data control
Docker Deployment
docker run -d -p 8080:8080 \
-e PORT=8080 \
-v vdoninja_data:/app/data \
steveseguin/vdo.ninja
9. Watchtower – Automated Docker Container Updates
Watchtower is a lightweight Docker container that automatically monitors and updates running containers whenever a new image version is available. A set-and-forget solution for keeping a self-hosted Docker stack up to date without manual intervention.
Features
- Automatically pulls and redeploys updated container images
- Configurable schedules via cron expressions or polling intervals
- Per-container opt-out via labels for selective update control
- Notification support including email, Slack, ntfy, and Apprise
Docker Deployment
docker run -d \
--name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower
10. Garage – Lightweight Self-Hosted S3-Compatible Object Storage
Garage is an open-source, self-hosted distributed object storage service with an S3-compatible API. Designed for small to medium infrastructure where a full MinIO setup would be overkill, offering resilient storage across multiple nodes with minimal resource usage.
Features
- S3-compatible API – works with existing S3 clients and SDKs
- Distributed across multiple nodes with configurable replication
- Designed for geo-distributed and low-bandwidth environments
- Lightweight binary with low memory footprint – no JVM or heavy runtime
Docker Deployment
docker run -d \
--name garage \
-p 3900:3900 -p 3901:3901 \
-v garage_data:/var/lib/garage/data \
-v garage_meta:/var/lib/garage/meta \
-v /etc/garage/garage.toml:/etc/garage/garage.toml \
dxflrs/garage
11. Mercure – Self-Hosted Real-Time Push Protocol
Mercure is an open-source protocol and server for pushing real-time updates to web browsers and other HTTP clients via Server-Sent Events. A lightweight alternative to WebSockets for live data feeds, notifications, and collaborative features built on standard HTTP.
Features
- Server-Sent Events over HTTP/2 – no WebSocket upgrade required
- JWT-based authorization for secure topic subscriptions and publishing
- Topic-based pub/sub with wildcard and private topic support
- Built-in metrics, health check endpoint, and high-performance Go runtime
Docker Deployment
docker run -d -p 3000:3000 \
-e SERVER_NAME=:3000 \
-e MERCURE_PUBLISHER_JWT_KEY=your_publisher_jwt_key \
-e MERCURE_SUBSCRIBER_JWT_KEY=your_subscriber_jwt_key \
-v mercure_data:/data \
dunglas/mercure
12. Apprise – Universal Notification Gateway
Apprise is an open-source notification library and self-hostable API server that provides a single unified interface for sending alerts to virtually any notification service. A practical abstraction layer for centralizing notifications across a self-hosted infrastructure stack.
Features
- 100+ supported notification services including Slack, Telegram, and ntfy
- Simple URL-based configuration for defining notification targets
- REST API server mode for sending notifications from any application or script
- Persistent notification groups via configuration files or the web UI
Docker Deployment
docker run -d -p 8000:8000 \
-v apprise_config:/config \
caronc/apprise
13. Duplicati – Self-Hosted Encrypted Cloud Backup
Duplicati is a free, open-source backup client with a web-based interface for scheduling encrypted, incremental backups to a wide range of local and cloud storage destinations. A reliable set-and-forget backup solution for self-hosted environments that prioritizes simplicity without sacrificing security.
Features
- AES-256 client-side encryption before data leaves the machine
- Incremental backups with deduplication to minimize storage usage
- Supports S3, Backblaze B2, FTP, SFTP, WebDAV, and 30+ backends
- Web UI with scheduling, retention policies, and email notifications
Docker Deployment
docker run -d -p 8200:8200 \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/Berlin \
-v duplicati_config:/config \
-v duplicati_backups:/backups \
-v /path/to/source:/source:ro \
lscr.io/linuxserver/duplicati
14. GoAccess – Real-Time Web Log Analyzer
GoAccess is an open-source, real-time web log analyzer and interactive viewer that runs directly in the terminal or generates self-contained HTML reports. A fast, dependency-free alternative to sending access logs to external analytics platforms, keeping traffic analysis entirely on-premise.
Features
- Real-time log parsing with live terminal dashboard and HTML report export
- Supports Nginx, Apache, Caddy, and custom log formats out of the box
- Visitor analytics including geolocation, browsers, OS, and referrers
- WebSocket-powered live HTML reports with no external dependencies
Docker Deployment
docker run -d -p 7890:7890 \
--name goaccess \
-v /path/to/nginx/logs:/var/log/nginx:ro \
-v goaccess_data:/srv/data \
-e LANG=en_US.UTF-8 \
allinurl/goaccess \
--log-format=COMBINED \
--real-time-html \
--output=/srv/data/report.html \
/var/log/nginx/access.log
15. Typebot – Self-Hosted Conversational Form Builder
Typebot is an open-source, self-hosted conversational form and chatbot builder with a visual flow editor. A privacy-friendly alternative to Typeform or Landbot for creating engaging multi-step forms, lead generation flows, and customer-facing chat interfaces without sending data to third-party servers.
Features
- Visual drag-and-drop flow builder with conditional logic and branching
- Embeddable as a popup, inline widget, or full-page chat interface
- Native integrations with Google Sheets, Webhooks, Zapier, and more
- Detailed analytics per block with drop-off rates and completion tracking
Docker Deployment
docker run -d -p 3000:3000 \
-e DATABASE_URL=postgresql://user:password@your_db_host:5432/typebot \
-e NEXTAUTH_URL=http://localhost:3000 \
-e NEXTAUTH_SECRET=your_nextauth_secret \
-e ENCRYPTION_SECRET=your_encryption_secret \
-v typebot_data:/app/data \
baptistearno/typebot-builder
16. Opengist – Self-Hosted Gist and Code Snippet Manager
Opengist is a lightweight, self-hosted pastebin and code snippet manager powered by Git. A privacy-friendly alternative to GitHub Gist with syntax highlighting, public and private snippets, and a familiar Git-based backend for version-controlled snippet history.
Features
- Git-backed snippet storage with full revision history per gist
- Syntax highlighting for 100+ languages with raw and download access
- Public, unlisted, and private snippet visibility options
- OAuth login support for GitHub, Gitea, and OpenID Connect
Docker Deployment
docker run -d -p 6157:6157 \
-e OG_SECRET_KEY=your_secret_key \
-e OG_EXTERNAL_URL=http://localhost:6157 \
-v opengist_data:/opengist \
ghcr.io/thomiceli/opengist
17. Imaginary – Self-Hosted Image Processing Microservice
Imaginary is a fast, self-hosted HTTP microservice for real-time image processing and transformation built on top of libvips. A lightweight alternative to cloud-based image APIs like Cloudinary or Imgix, designed for high-throughput resizing, cropping, and format conversion without external dependencies.
Features
- Real-time image resizing, cropping, rotation, and format conversion via HTTP
- Supports JPEG, PNG, WebP, AVIF, GIF, TIFF, and SVG input formats
- URL-based and multipart form API for flexible integration
- High performance via libvips – significantly faster than ImageMagick
Docker Deployment
docker run -d -p 9000:9000 \
-e PORT=9000 \
-e IMAGINARY_KEY=your_api_key \
-e IMAGINARY_ALLOWED_ORIGINS=http://localhost \
h2non/imaginary \
-enable-url-source \
-key your_api_key
18. Puppeteer Renderer – Self-Hosted Headless Browser Rendering Service
Puppeteer Renderer is a self-hosted HTTP service that uses a headless Chromium browser via Puppeteer to render JavaScript-heavy pages and generate PDFs or screenshots on demand. A practical microservice for server-side rendering, PDF generation, and web scraping without managing a browser runtime directly in your application.
Features
- Full-page screenshots and PDF generation via simple HTTP requests
- Server-side rendering of JavaScript-heavy Single Page Applications
- Configurable viewport, wait conditions, and page timeout options
- Lightweight HTTP API – easily callable from PHP, Node.js, or any backend
Docker Deployment
docker run -d -p 3000:3000 \
--cap-add SYS_ADMIN \
zenato/puppeteer-renderer:2.4.0
Glossary
New to Docker? Here’s a quick-reference for the terms you’ll run into constantly:
Term | What it means |
|---|---|
Image | The read-only blueprint for a container — think of it as a recipe. It packages your app, runtime, and config into a portable layered file. |
Container | A running instance of an image. Isolated process with its own filesystem and network. One image, many containers. |
Dockerfile | A plain-text script of build instructions ( FROM, RUN, COPY, CMD) that Docker reads to assemble an image. |
Docker Compose | A tool for defining multi-container apps in a single YAML file instead of chaining docker run commands. |
compose.yaml | The modern name for the Compose config file. Replaces the old docker-compose.yml (both still work). |
Named Volume | Storage fully managed by Docker, tucked away in Docker’s own area on the host. Preferred for databases and persistent app data. |
Bind Mount | A specific host directory mapped directly into the container. Great for development; handle permissions carefully in production. |
Registry | A server that stores and serves Docker images. Docker Hub is the default public one. |
Docker Hub | The default public image registry at hub.docker.com. Rate-limited for unauthenticated pulls since 2025. |
Tag | A version label on an image, e.g. nginx:1.27-alpine. The latest tag is a floating pointer — never pin production to it. |
Layer | Each instruction in a Dockerfile creates a cached, immutable layer. Unchanged layers are reused on rebuild for speed. |
Multi-stage Build | Using multiple FROM statements in one Dockerfile to build in a fat SDK image, then copy only the output into a lean runtime image. |
docker.sock | The Unix socket the Docker daemon listens on. Mounting it into a container gives that container full Docker daemon access — powerful and risky. |
Healthcheck | A command Docker runs inside a container on a schedule to decide if it’s healthy, unhealthy, or starting. Used by Compose depends_on. |
Reverse Proxy | A front-end server (Nginx Proxy Manager, Traefik, Caddy) that routes incoming traffic to the right container by hostname or path. |
Network (Docker) | An isolated virtual network. Containers on the same user-defined network can reach each other by service name via Docker’s internal DNS. |
Port Mapping | The -p hostPort:containerPort flag. Left side = your host, right side = inside the container. |
ENTRYPOINT | The executable that always runs when a container starts. Unlike CMD, it can’t be overridden by just passing arguments — only by --entrypoint. |
PID 1 | The first process in a container. Linux treats it specially: it must handle signals and reap zombie child processes. Use exec-form ENTRYPOINT or add --init. |
FAQ
What is the difference between a Docker image and a Docker container?
A Docker image is a read-only blueprint — it packages your application code, runtime, libraries, and configuration into a layered, portable file. A container is a live, running instance of that image with its own isolated process, filesystem, and network interface.
Images are blueprints; containers are running instances. You can create many containers from one image, each running independently.
How does Docker differ from a virtual machine?
Virtual machines run complete guest OSes on a hypervisor, requiring gigabytes of RAM per instance. Docker containers share the host OS kernel directly using Linux namespaces and cgroups. Containers start in seconds versus minutes, consume far less memory, and offer better portability.
The trade-off is reduced isolation compared to full VMs — for most self-hosted workloads, that’s an acceptable trade.
What is a Dockerfile and how does it work?
A Dockerfile is a plain text script that tells Docker how to build an image step by step. Each instruction — FROM, RUN, COPY, ENV, CMD — creates a new read-only layer on top of the previous one.
The FROM instruction defines the base image. Running docker build -t myapp:1.0 . produces a tagged image ready to run. Docker caches unchanged layers for faster rebuilds.
What is Docker Compose and when should I use it?
Docker Compose defines multi-container applications in a single compose.yaml file instead of running multiple docker run commands. Use it whenever your application requires multiple containers — databases, caching layers, web services.
The modern syntax is docker compose (with a space), replacing the deprecated hyphenated docker-compose command.
What is the difference between a named volume and a bind mount?
A named volume (-v mydata:/var/lib/data) is fully managed by Docker and stored inside Docker’s own storage area on the host. A bind mount (-v /host/path:/container/path) maps a specific directory from your host filesystem directly into the container.
Named volumes are preferred for production data; bind mounts are useful during development when you want to edit files live.
Why does my container lose all data when I restart or remove it?
Data written inside a container’s filesystem exists only for that container’s lifetime. When the container is removed, the data disappears. Mount a named volume or bind mount at the application’s data path to persist information across restarts and replacements.
Always check the image documentation for which paths need to be mounted.
How do container ports and port mapping work?
Containers operate in isolated network namespaces with their own internal ports. Use -p 8080:80 to map host port 8080 to container port 80 — left side is always the host, right is always the container.
To restrict access to localhost only, use -p 127.0.0.1:5432:5432 so the service doesn’t bind to your public interface.
How do containers communicate with each other?
Containers on the same user-defined Docker network resolve each other by service name using Docker’s internal DNS. In Compose stacks, all services share a default network, enabling direct hostname connections.
Never use localhost inside containers to reach other containers — localhost refers to the container itself, not the host or its neighbors.
Should I use the latest tag for images in production?
No. The latest tag is a floating pointer that changes without warning. Always pin images to specific version tags like postgres:16.2-alpine3.19 to ensure reproducible deployments and prevent surprise breakage on the next pull.
Reserve latest for local experiments only, and use tools like Watchtower for controlled automated updates.
How do I pass environment variables into a container securely?
Use an .env file in the Compose directory and reference variables with ${VARIABLE_NAME} syntax in your compose.yaml. Add .env to .gitignore and commit only an .env.example template.
For production, inject variables through CI/CD pipeline secret management rather than shipping .env files on the server.
What restart policies are available and which should I use?
Docker offers four restart policies: no (default — no restart), always (restart including after daemon reboot), unless-stopped (restart unless manually stopped before reboot), and on-failure (restart only on non-zero exit).
For self-hosted stacks, restart: unless-stopped is the practical default — it survives reboots but respects intentional stops.
How do I view logs from a running container?
Use docker logs <container_name> to print output. Add -f to follow logs in real time, --tail 100 for the last 100 lines, or --since 1h for the past hour.
Configure log rotation in /etc/docker/daemon.json with "log-opts": {"max-size": "10m", "max-file": "3"} to prevent logs from eating your disk.
How do I get a shell inside a running container?
Run docker exec -it <container_name> /bin/bash to open an interactive shell. If bash isn’t installed, try /bin/sh. The -i flag keeps stdin open; -t allocates a pseudo-TTY.
In Compose, use docker compose exec servicename /bin/sh.
What are multi-stage builds and why should I use them?
Multi-stage builds use multiple FROM instructions to separate build environments from runtime environments. Build in a full SDK image, then copy only compiled output to a minimal runtime image like Alpine.
This dramatically reduces image size, shrinks the attack surface, and speeds up deployments. Multi-stage builds should be the default for any custom image going to production.
How do I make sure a dependent service is ready before my app container starts?
Use depends_on with condition: service_healthy after defining a healthcheck on the dependency. For example, define a healthcheck on your database service using pg_isready or mysqladmin ping, and Compose will hold the app container until the health check passes.
As a fallback, wrapper scripts like wait-for-it.sh work for images you can’t control.
How do I reduce the size of my Docker images?
Start with minimal base images — Alpine variants are typically 5–10x smaller than full Debian. Use multi-stage builds to exclude build tools from the final image. Chain RUN commands with && and clean package caches in the same layer.
Use .dockerignore to exclude node_modules, .git, and build artifacts. Every layer you avoid is attack surface you don’t have.
How do I free up disk space taken up by Docker?
Run docker system prune to remove stopped containers, dangling images, unused networks, and build cache. Add -a to also remove images not referenced by any running containers. Check consumption first with docker system df.
For surgical cleanup: docker image prune -a, docker volume prune, and docker builder prune.
Should I run containers as root?
No. Running as root inside a container is a security risk — if the container is compromised, root inside often means elevated access outside. Define a non-root user in Dockerfiles using the USER instruction after installing dependencies.
Many official images already run as non-root. For containers that need host resource access, restrict scope with specific capabilities rather than --privileged.
What is the difference between docker compose up, start, and run?
docker compose up creates and starts all services, building images if necessary — add -d for detached (background) mode. docker compose start only starts services already created but currently stopped.
docker compose run starts a one-off container for a specific service, overriding default commands — ideal for migrations or interactive shells without spinning up the whole stack.
How do I update a running container to a new image version?
With Compose, update the image tag in compose.yaml, run docker compose pull, then docker compose up -d. Compose recreates only containers whose images changed.
For single containers, manually pull the new image, stop and remove the old container, then run the new tag with the same flags and volume mounts.
What is /var/run/docker.sock and why do some containers need it?
/var/run/docker.sock is the Unix socket the Docker daemon listens on. Mounting it into a container gives that container the ability to communicate with the Docker daemon — allowing it to manage other containers, pull images, and inspect the environment.
Tools like Portainer and Watchtower require it. Treat it as a security boundary: never expose it to untrusted or public-facing containers.
How do I limit CPU and memory usage for a container?
Resource limits prevent a misbehaving container from starving other services. In a Compose file, define limits under the deploy.resources key: limits.memory: 512M caps RAM and limits.cpus: '1.0' caps CPU.
With plain docker run, use --memory 512m and --cpus 1.0 flags. Always set sensible limits on shared hosts — one runaway container can take down everything else.
What is Docker Hub and are there alternatives?
Docker Hub is the default public registry at hub.docker.com. As of 2025, Docker Hub enforces rate limits for unauthenticated pulls. Alternatives include GitHub Container Registry (ghcr.io) — many open-source projects’ preferred primary registry.
Self-hosted options like Harbor or a plain Docker Registry container give you full control over your own image storage.
When does Docker make sense and when should I use something else?
Docker excels at packaging applications with dependencies, standardizing development environments, and running self-hosted services on a single host via Compose. For high availability across multiple nodes, Kubernetes or Docker Swarm becomes relevant.
Docker isn’t ideal for GUI applications, workloads requiring direct hardware access, or setups deeply dependent on specific kernel versions. Compose handles most real-world self-hosted needs without the Kubernetes complexity overhead.
What is Docker BuildKit and why should I enable it?
BuildKit is Docker’s modern build backend, replacing the legacy builder. It’s enabled by default in Docker 23.0+, but on older setups you can force it with DOCKER_BUILDKIT=1 before docker build.
BuildKit brings parallel layer building, better cache management, secret mounting via --mount=type=secret, and significantly faster builds. If you’re still using the old builder, you’re leaving performance on the table.
What is the difference between ENTRYPOINT and CMD in a Dockerfile?
ENTRYPOINT defines the executable that always runs — it’s the fixed part of the command. CMD provides default arguments that can be overridden when running the container. When both are present in exec form, they combine: ENTRYPOINT ["nginx"] + CMD ["-g", "daemon off;"] runs as nginx -g daemon off;.
Arguments passed to docker run replace CMD but not ENTRYPOINT. Always prefer exec form (["executable", "arg"]) over shell form for both — shell form wraps in /bin/sh -c and breaks signal handling.
How do I debug a container that keeps restarting?
First check the exit code and recent logs: docker logs --tail 50 <container_name>. If the container restarts too fast to catch, temporarily override the entrypoint: docker run --entrypoint /bin/sh -it <image_name> to get a shell and poke around.
Common culprits are missing environment variables, failed database connections on startup, or a CMD that exits immediately. Set restart: no while debugging so it doesn’t loop.
What does the EXPOSE instruction in a Dockerfile actually do?
EXPOSE is documentation — it tells humans and tools which port the service listens on inside the container. It does NOT publish the port to the host or open any firewall rules.
You still need -p hostPort:containerPort in docker run or a ports: entry in Compose to actually make the port reachable from outside. Think of EXPOSE as a well-placed comment.
How do I handle Docker secrets more securely than .env files?
For production, use Docker Swarm secrets or a secrets manager like HashiCorp Vault, AWS Secrets Manager, or Doppler. In Compose, named secrets are injected as files under /run/secrets/ inside the container — your app reads the file instead of an environment variable.
This prevents secrets from appearing in docker inspect output or environment dumps. At minimum, keep .env files out of version control and off shared servers.
What are Docker labels and what can I use them for?
Labels are key-value metadata you attach to images, containers, volumes, or networks — either in your Dockerfile with LABEL or via docker run --label. Traefik uses container labels to auto-configure routing. Watchtower uses labels to opt containers in or out of updates.
They’re also useful for filtering: docker ps --filter label=env=production lists only your production containers.
How do I back up and restore Docker volumes?
The standard approach: spin up a temporary Alpine container that mounts your volume and tars the contents to a backup directory on the host.
For databases, always use native dump tools like pg_dump or mysqldump instead of raw volume backups — file-level backups of a live database can be inconsistent.
What is the difference between docker stop and docker kill?
docker stop sends SIGTERM to the container’s PID 1, giving the process a chance to shut down gracefully — flushing buffers, closing connections, finishing in-flight requests. It waits 10 seconds before sending SIGKILL if the process doesn’t exit.
docker kill sends SIGKILL immediately with no grace period and no cleanup. Always use docker stop for production containers; use docker kill only when a container is genuinely stuck.
How do I install Docker on a fresh Ubuntu or Debian VPS?
The official one-liner from Docker’s apt repository is the cleanest approach: curl -fsSL https://get.docker.com | sh. Then add your user to the docker group so you don’t need sudo for every command: sudo usermod -aG docker $USER && newgrp docker.
Verify with docker run hello-world. Always install from the official Docker apt repo rather than the distro’s older package to get current releases and security patches.
What is the difference between Docker Swarm and Kubernetes?
Docker Swarm is Docker’s built-in clustering mode — it uses the same Compose YAML format and is dramatically simpler to set up. It’s a solid choice for small teams running a handful of nodes. Kubernetes is the industry standard for large-scale orchestration with auto-scaling, rolling updates, and a massive ecosystem.
Kubernetes comes with significant operational complexity. For most self-hosters, Swarm covers the gap between single-host Compose and full Kubernetes without the learning cliff.
How do I scan Docker images for security vulnerabilities?
Docker Scout is the built-in tool: docker scout cves <image_name> gives you a CVE breakdown. Trivy is a popular open-source alternative: docker run --rm aquasec/trivy image nginx:latest. Grype is another fast option.
Integrate scanning into your CI pipeline so you catch vulnerabilities before they reach production. Always prefer minimal base images like Alpine or distroless to reduce the vulnerability surface to begin with.
What is PID 1 and why does it matter in containers?
In Linux, PID 1 is the first process in a container and the kernel treats it differently from all others. It must handle signals like SIGTERM for graceful shutdown and reap zombie child processes. When Docker stops a container, SIGTERM goes to PID 1.
If your app uses shell-form CMD or ENTRYPOINT, it runs as a child of /bin/sh which often doesn’t forward signals, causing docker stop to time out and fall back to SIGKILL. Fix it with exec-form ENTRYPOINT or add --init to inject Docker’s built-in Tini init process.
