When deploying a LEMP stack with Docker containers, you might encounter the frustrating error:
[emerg] 1#1: host not found in upstream "php-fpm:9000" in /etc/nginx/conf.d/upstream.conf:1
This typically occurs when Nginx can't resolve the PHP-FPM container's hostname. While the setup works locally, production deployments often fail due to differences in container networking.
The key difference lies in how Docker handles container networking between environments:
# Local development (working)
docker-compose up -d
# Containers can resolve each other's names automatically
# Production (failing)
docker run -d nginx
docker run -d php-fpm
# Containers can't discover each other without explicit networking
Solution 1: Using Docker Compose with Explicit Links
For development/production parity, use this docker-compose.yml:
version: '3'
services:
nginx:
image: nginx:latest
ports:
- "80:80"
depends_on:
- php
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
links:
- php:php-fpm
php:
image: php:7.4-fpm
volumes:
- ./code:/var/www/html
Solution 2: Custom Network Configuration
For standalone Docker deployments:
# Create a custom network
docker network create lemp_network
# Run PHP-FPM container
docker run -d --name php-fpm --network lemp_network php:7.4-fpm
# Run Nginx container
docker run -d --name nginx --network lemp_network -p 80:80 nginx
Solution 3: Environment Variables in Production
Modify your Nginx Dockerfile to handle dynamic upstreams:
FROM nginx:latest
# Use environment variables with defaults
RUN echo "upstream php-upstream { server ${PHP_FPM_HOST:-php-fpm}:${PHP_FPM_PORT:-9000}; }" > /etc/nginx/conf.d/upstream.conf
CMD ["nginx", "-g", "daemon off;"]
Then run with:
docker run -d -e PHP_FPM_HOST=your_php_container_name nginx
If you're still facing issues:
# Check container networking
docker network inspect bridge
# Test DNS resolution from within Nginx container
docker exec -it nginx_container ping php-fpm
# Verify container links
docker inspect nginx_container | grep Links
For production environments, consider:
- Using Docker Swarm or Kubernetes with proper service discovery
- Implementing health checks in your containers
- Setting up proper restart policies
Here's a robust production-grade docker-compose.yml snippet:
services:
nginx:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
deploy:
restart_policy:
condition: on-failure
php:
healthcheck:
test: ["CMD-SHELL", "php -v"]
interval: 30s
When deploying a LEMP stack with Docker containers, you might encounter this frustrating error in your Nginx logs:
[emerg] 1#1: host not found in upstream "php-fpm:9000" in /etc/nginx/conf.d/upstream.conf:1
The error occurs when Nginx can't resolve the hostname of your PHP-FPM container, typically during container startup.
The key difference between local and production environments often comes down to:
- Different Docker networking configurations
- Missing or misconfigured container dependencies
- Environment variables not being properly passed
- DNS resolution timing issues during container startup
Here are several approaches that have worked for developers:
1. Using Docker's Internal DNS
Modify your Nginx configuration to use Docker's internal networking:
upstream php-upstream {
server php-fpm:9000;
}
And ensure your docker-compose.yml has:
version: '3'
services:
nginx:
depends_on:
- php-fpm
networks:
- app-network
php-fpm:
networks:
- app-network
networks:
app-network:
driver: bridge
2. Custom Network Solution
Create a custom network and explicitly name your services:
docker network create lemp-network
Then in docker-compose.yml:
services:
nginx:
networks:
lemp-network:
aliases:
- nginx-service
php-fpm:
networks:
lemp-network:
aliases:
- php-fpm-service
3. Startup Order Control
Add a health check and wait-for script:
healthcheck:
test: ["CMD", "nc", "-z", "php-fpm", "9000"]
interval: 5s
timeout: 5s
retries: 5
For production environments, consider these additional measures:
# In your Nginx Dockerfile
RUN echo "resolver 127.0.0.11 valid=30s;" >> /etc/nginx/nginx.conf
This configures Nginx to use Docker's embedded DNS server with proper caching settings.
After implementing any solution, verify with:
docker exec -it nginx-container cat /etc/nginx/conf.d/upstream.conf
docker exec -it nginx-container nslookup php-fpm