Using Hosts Files for Docker Development on Mac
Learn how to configure hosts files for Docker, docker-compose, and container networking. Map container services to local domains and streamline your Docker development workflow.
Locahl Team
Table of Contents
- Understanding Docker Networking Basics
- Docker Desktop Networking Architecture
- Container-to-Container Communication
- Setting Up Custom Domains for Docker Services
- Basic Hosts File Configuration
- Using Standard Ports with Multiple Services
- Wildcard Domains for Subdomains
- Docker Compose Multi-Service Architecture
- Microservices Setup
- Service Discovery Within Docker
- Advanced Docker Networking Patterns
- Custom Docker Networks
- External Networks
- Host Network Mode (Linux Only)
- Port Management Strategies
- Avoiding Port Conflicts
- Standard Ports with Reverse Proxy
- Docker and Local HTTPS
- Generating SSL Certificates for Docker Services
- Configuring HTTPS in Docker
- Traefik with Automatic HTTPS
- Organizing Hosts File Entries for Docker
- Project-Based Organization
- Environment-Based Organization
- Docker Compose Override Patterns
- Development Overrides
- Multiple Compose Files
- Troubleshooting Docker Hosts File Issues
- Containers Not Accessible via Custom Domain
- Port Already in Use
- DNS Resolution Issues
- Container-to-Container Communication Fails
- Best Practices for Docker Hosts File Management
- 1. Use Consistent Naming Conventions
- 2. Document Port Mappings
- Local Development
- 3. Version Control Hosts File Templates
- 4. Use Environment-Specific Domains
- 5. Automate Hosts File Updates
- Integration with Development Tools
- Hot Reload and Volume Mounts
- Database Access
- Debugging Tools
- Conclusion
Docker has revolutionized local development by providing isolated, reproducible environments. However, accessing your containers via custom domain names requires careful coordination between Docker networking and your Mac's hosts file. This guide will show you how to seamlessly integrate hosts file management with Docker, docker-compose, and container networking.
Understanding Docker Networking Basics
Before diving into hosts file configuration, it's essential to understand how Docker networking works on macOS.
Docker Desktop Networking Architecture
Docker Desktop on Mac runs containers inside a Linux VM. When you map ports using -p or ports: in docker-compose, Docker creates a bridge between the container's network and your Mac's localhost.
services:
web:
image: nginx:alpine
ports:
- "8080:80" # Host:ContainerThis means:
- Port 8080 on your Mac maps to port 80 in the container
- You can access it via
localhost:8080or127.0.0.1:8080 - To use a custom domain, add a hosts file entry pointing to 127.0.0.1
Container-to-Container Communication
Containers within the same Docker network can communicate using service names defined in docker-compose.yml. This doesn't require hosts file modifications:
services:
web:
image: nginx:alpine
depends_on:
- api
api:
image: node:18
expose:
- "3000"The web container can reach the API at http://api:3000 without any hosts file configuration.
Simplify your hosts file management
Locahl lets you manage your hosts file visually, without touching the terminal. Automatic DNS flush, multiple environments, and backups included.
Setting Up Custom Domains for Docker Services
Basic Hosts File Configuration
The simplest approach is to map each Docker service to a custom domain:
# /etc/hosts
127.0.0.1 api.docker.test
127.0.0.1 frontend.docker.test
127.0.0.1 admin.docker.testThen in your docker-compose.yml:
version: '3.8'
services:
api:
image: node:18
ports:
- "3001:3000"
frontend:
image: nginx:alpine
ports:
- "3002:80"
admin:
image: nginx:alpine
ports:
- "3003:80"Access your services at:
http://api.docker.test:3001http://frontend.docker.test:3002http://admin.docker.test:3003
Using Standard Ports with Multiple Services
If you prefer standard ports (80, 443), you'll need to run only one service per port. Use different domains:
# /etc/hosts
127.0.0.1 api.docker.test
127.0.0.1 frontend.docker.testservices:
api:
image: node:18
ports:
- "80:3000" # Access via api.docker.test:80
frontend:
image: nginx:alpine
ports:
- "8080:80" # Different port for frontendWildcard Domains for Subdomains
For applications with dynamic subdomains, use wildcard DNS with dnsmasq:
# Install dnsmasq
brew install dnsmasq
# Configure wildcard for .docker.test
echo "address=/.docker.test/127.0.0.1" >> /usr/local/etc/dnsmasq.conf
# Create resolver
sudo mkdir -p /etc/resolver
echo "nameserver 127.0.0.1" | sudo tee /etc/resolver/docker.test
# Start dnsmasq
sudo brew services start dnsmasqNow any *.docker.test domain automatically resolves to localhost!
Docker Compose Multi-Service Architecture
Microservices Setup
For complex applications with multiple services:
version: '3.8'
services:
# Backend API
api:
build: ./api
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://db:5432/myapp
depends_on:
- db
# Frontend Application
frontend:
build: ./frontend
ports:
- "3001:3000"
environment:
- API_URL=http://api:3000
# Admin Panel
admin:
build: ./admin
ports:
- "3002:3000"
# Database
db:
image: postgres:15
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
# Redis Cache
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:Hosts file configuration:
# /etc/hosts
# Docker Services
127.0.0.1 api.docker.test
127.0.0.1 frontend.docker.test
127.0.0.1 admin.docker.testService Discovery Within Docker
Containers discover each other using service names. The frontend container can call the API at http://api:3000 because Docker's internal DNS resolves api to the container's IP.
For external access (from your Mac), use the hosts file entries and mapped ports.
Advanced Docker Networking Patterns
Custom Docker Networks
Create isolated networks for different environments:
version: '3.8'
networks:
frontend_network:
driver: bridge
backend_network:
driver: bridge
services:
frontend:
image: nginx:alpine
networks:
- frontend_network
ports:
- "80:80"
api:
image: node:18
networks:
- backend_network
- frontend_network
ports:
- "3000:3000"The api service is accessible from both networks, while frontend only sees the API through the shared network.
External Networks
Connect containers to existing networks:
services:
web:
image: nginx:alpine
networks:
- existing_network
networks:
existing_network:
external: trueHost Network Mode (Linux Only)
On Linux, you can use host networking mode. On macOS, this isn't directly supported, but you can achieve similar results with port mapping.
Port Management Strategies
Avoiding Port Conflicts
When running multiple Docker projects, port conflicts are common. Strategies:
1. Use Different Port Ranges
# Project A
services:
web:
ports:
- "8000:80"
# Project B
services:
web:
ports:
- "8001:80"2. Use Environment Variables
services:
web:
ports:
- "\$\{WEB_PORT:-8080}:80"# .env file
WEB_PORT=90003. Dynamic Port Assignment
services:
web:
ports:
- "0:80" # Docker assigns random portCheck assigned port: docker ps or docker-compose ps
Standard Ports with Reverse Proxy
Use a reverse proxy (Traefik, Nginx) to route based on domain names:
version: '3.8'
services:
traefik:
image: traefik:v2.10
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
api:
image: node:18
labels:
- "traefik.http.routers.api.rule=Host(`api.docker.test`)"
- "traefik.http.services.api.loadbalancer.server.port=3000"
frontend:
image: nginx:alpine
labels:
- "traefik.http.routers.frontend.rule=Host(`frontend.docker.test`)"With hosts file entries, all services accessible on port 80 via their domains.
Docker and Local HTTPS
Generating SSL Certificates for Docker Services
Use mkcert to create trusted certificates:
# Install mkcert
brew install mkcert
mkcert -install
# Create certificate for Docker services
mkcert api.docker.test frontend.docker.test "*.docker.test"Configuring HTTPS in Docker
services:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./api.docker.test.pem:/etc/nginx/ssl/cert.pem
- ./api.docker.test-key.pem:/etc/nginx/ssl/key.pemTraefik with Automatic HTTPS
Traefik can automatically handle HTTPS:
services:
traefik:
image: traefik:v2.10
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./certs:/certsOrganizing Hosts File Entries for Docker
Project-Based Organization
Group entries by project:
# ===================
# DOCKER PROJECT: E-commerce Platform
# ===================
127.0.0.1 shop.docker.test
127.0.0.1 api.shop.docker.test
127.0.0.1 admin.shop.docker.test
# ===================
# DOCKER PROJECT: Blog Platform
# ===================
127.0.0.1 blog.docker.test
127.0.0.1 cms.blog.docker.testEnvironment-Based Organization
Separate by environment:
# ===================
# DOCKER: Development
# ===================
127.0.0.1 dev-api.docker.test
127.0.0.1 dev-frontend.docker.test
# ===================
# DOCKER: Staging
# ===================
127.0.0.1 staging-api.docker.test
127.0.0.1 staging-frontend.docker.testDocker Compose Override Patterns
Development Overrides
Use docker-compose.override.yml for local development:
# docker-compose.yml (base)
version: '3.8'
services:
api:
image: node:18
ports:
- "3000:3000"
# docker-compose.override.yml (local, gitignored)
version: '3.8'
services:
api:
volumes:
- ./src:/app/src # Hot reload
environment:
- NODE_ENV=developmentMultiple Compose Files
# Development
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
# Production-like
docker-compose -f docker-compose.yml -f docker-compose.prod.yml upTroubleshooting Docker Hosts File Issues
Containers Not Accessible via Custom Domain
Problem: Domain resolves but connection refused.
Solutions: 1. Verify port mapping: docker ps shows 0.0.0.0:PORT->... 2. Check container is running: docker-compose ps 3. Verify hosts file entry: ping api.docker.test should resolve to 127.0.0.1 4. Check firewall settings
Port Already in Use
Problem: Error: bind: address already in use
Solutions: 1. Find process using port: lsof -i :8080 2. Stop conflicting container: docker stop <container> 3. Change port mapping in docker-compose.yml 4. Use different port range
DNS Resolution Issues
Problem: Domain doesn't resolve.
Solutions: 1. Verify hosts file syntax (no extra spaces) 2. Flush DNS cache: sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder 3. Check dnsmasq if using wildcards 4. Restart Docker Desktop
Container-to-Container Communication Fails
Problem: Services can't reach each other.
Solutions: 1. Verify services are on same network: docker network inspect <network> 2. Use service names, not localhost 3. Check depends_on ordering 4. Verify expose/ports configuration
Best Practices for Docker Hosts File Management
1. Use Consistent Naming Conventions
# Good: Project-based naming
api.projectname.test
frontend.projectname.test
# Avoid: Generic names
api.test
web.test2. Document Port Mappings
Include port documentation in README:
## Local Development
- API: http://api.project.test:3000
- Frontend: http://frontend.project.test:8080
- Admin: http://admin.project.test:30013. Version Control Hosts File Templates
Create hosts.example in your project:
# hosts.example
127.0.0.1 api.project.test
127.0.0.1 frontend.project.test4. Use Environment-Specific Domains
# Development
dev-api.project.test
# Staging
staging-api.project.test
# Local
local-api.project.test5. Automate Hosts File Updates
Create a script to sync docker-compose services with hosts file:
#!/bin/bash
# sync-docker-hosts.sh
SERVICES=$(docker-compose config --services)
for service in $SERVICES; do
PORT=$(docker-compose config | grep -A 5 "$service:" | grep -oP 'd+:d+' | head -1 | cut -d: -f1)
echo "127.0.0.1 $service.docker.test" >> /tmp/docker-hosts
doneIntegration with Development Tools
Hot Reload and Volume Mounts
services:
api:
build: ./api
volumes:
- ./api/src:/app/src # Hot reload
ports:
- "3000:3000"Access via api.docker.test:3000 with automatic code reloading.
Database Access
services:
db:
image: postgres:15
ports:
- "5432:5432" # Expose for external toolsConnect from Mac using localhost:5432 or add db.docker.test to hosts file.
Debugging Tools
services:
api:
image: node:18
ports:
- "3000:3000"
- "9229:9229" # Node.js debuggerAttach debugger via api.docker.test:9229.
Conclusion
Effectively managing hosts files with Docker requires understanding both Docker networking and macOS DNS resolution. By following the patterns outlined in this guide, you can:
- Map container services to memorable domain names
- Avoid port conflicts across multiple projects
- Maintain clean, organized hosts file configurations
- Streamline your Docker development workflow
Remember to use .test domains to avoid conflicts, document your port mappings, and leverage tools like Locahl to manage your hosts file entries efficiently. With proper configuration, Docker and hosts files work together seamlessly to create a productive local development environment.
For teams working with Docker, consider using Locahl (β¬9.99) to share hosts file configurations, maintain consistency across environments, and eliminate the manual editing overhead. Locahl makes it easy to export, import, and sync hosts file entries across your entire team.
Ready to simplify your workflow?
Stop wasting time with the terminal. Locahl lets you manage your hosts file in a few clicks, with automatic validation and no risk of errors.
- Intuitive visual interface
- Automatic DNS flush
- Multi-environment management
- Automatic backups
- JSON Import/Export
Reader Reviews
"Finally, a clear guide on Docker and hosts files! The docker-compose networking section was exactly what I needed."
February 6, 2026
"The service mapping examples saved me hours of trial and error. Great practical advice for Docker workflows."
February 6, 2026
"Very comprehensive. Would have liked more on Docker Desktop networking specifics, but overall excellent guide."
February 6, 2026
Frequently Asked Questions
How do I access Docker containers via custom domains?
Map container ports to host ports in docker-compose.yml, then add entries to your hosts file pointing to 127.0.0.1. Use .test domains to avoid conflicts.
Do I need to modify hosts file for each Docker container?
Only if you want custom domain names. Containers can access each other by service name within the same Docker network without hosts file modifications.
How do Docker networks interact with the hosts file?
The hosts file only affects your Mac's DNS resolution. Docker containers use their own internal DNS and networks. Map host ports to access containers via hosts file entries.
Can I use .local domains with Docker on Mac?
Not recommended. .local domains conflict with macOS Bonjour. Use .test or .localhost instead for better performance and compatibility.
How do I share Docker hosts file configurations with my team?
Export your hosts file entries and include them in your project documentation. Tools like Locahl make it easy to share and sync hosts file configurations across team members.
Related Articles
Hosts File Setup for Laravel/WordPress Local Development
Complete guide to configuring hosts files for Laravel Valet, Herd, and WordPress local development. Learn custom domains (.test, .local), multisite configurations, and best practices.
Locahl Team
Local development environment on Mac: the complete guide (2026)
Set up a perfect local dev environment on macOS. MAMP vs Laravel Valet vs Docker comparison, .test domains, local HTTPS with mkcert. Complete checklist.
Locahl Team
Edit the hosts file on Mac: Terminal vs GUI (2026)
How to edit /etc/hosts on macOS without errors? Terminal (sudo nano) vs GUI comparison. Fix permission denied and DNS cache issues in 2 minutes.
Locahl Team