如何将基于Yii PHP的微服务应用Docker化(替代Vagrant)
Hey there! Let's walk through how to dockerize your 10 Yii-based PHP microservices stack to replace Vagrant—this is a super common transition, and I’ve helped teams work through similar setups plenty of times. Here’s a step-by-step, practical plan tailored to your setup:
Start by mapping your existing Vagrant setup to a container-native structure:
- Service Layer: Each Yii microservice gets its own isolated PHP-FPM container (no shared runtime environments anymore).
- Middleware Layer: Run shared components (MongoDB, Redis, RabbitMQ, Elasticsearch) as separate, managed containers using official images.
- Gateway Layer: Keep Nginx as a unified reverse proxy to route traffic to the correct microservice.
- Orchestration: Use Docker Compose for your development environment (it’s perfect for multi-service stacks and mimics production behavior closely). For production later, you can transition to Kubernetes if needed.
Each service needs a custom Dockerfile—here’s a production-ready, multi-stage example optimized for Yii:
# Stage 1: Install Composer dependencies (keeps final image small) FROM composer:latest AS composer-builder WORKDIR /app COPY composer.json composer.lock ./ # For development, remove --no-dev to keep dev dependencies RUN composer install --no-dev --optimize-autoloader # Stage 2: Build the runtime image FROM php:7.4-fpm-alpine # Match your Yii version's required PHP version WORKDIR /var/www/html # Install system & PHP extensions Yii needs (adjust based on your service's requirements) RUN apk add --no-cache git zip unzip \ && docker-php-ext-install mbstring gd \ && pecl install mongodb redis amqp \ && docker-php-ext-enable mongodb redis amqp # Copy pre-installed Composer dependencies from the builder stage COPY --from=composer-builder /app/vendor ./vendor # Copy your Yii application code COPY . . # Set correct permissions for Yii's writable directories (runtime, web/assets) RUN chown -R www-data:www-data runtime web/assets
For development, add a volume mount in your docker-compose.yml to sync local code with the container—this lets you edit files without rebuilding the image every time.
Use official, maintained images for your middleware (no need to build these from scratch):
- MongoDB: Use
mongo:5.0(or your preferred version) with a persistent volume to avoid data loss on container restarts. - Nginx: Create a custom config to route requests to each microservice’s PHP-FPM container. Example snippet:
server { listen 80; server_name local.your-stack.com; location /service1/ { fastcgi_pass service1-fpm:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; include fastcgi_params; } # Repeat similar blocks for service2-service10 } - Redis:
redis:alpine(lightweight, perfect for dev) with a persistent volume. - RabbitMQ:
rabbitmq:3-management-alpine(includes a web UI at port 15672 for debugging). - Elasticsearch:
elasticsearch:7.17.0(setdiscovery.type=single-nodefor dev, and limit Java memory withES_JAVA_OPTS="-Xms512m -Xmx512m").
Create a docker-compose.yml to tie all services together. Here’s a condensed example:
version: '3.8' services: # Nginx Gateway nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx/conf.d:/etc/nginx/conf.d depends_on: - service1-fpm - service2-fpm # Add all 10 services here # Example Yii Microservice 1 service1-fpm: build: ./services/service1 volumes: - ./services/service1:/var/www/html # Sync local code for dev environment: - DB_HOST=mongo - REDIS_HOST=redis - RABBITMQ_HOST=rabbitmq depends_on: - mongo - redis # Example Yii Microservice 2 service2-fpm: build: ./services/service2 volumes: - ./services/service2:/var/www/html environment: - DB_HOST=mongo - ELASTIC_HOST=elasticsearch depends_on: - mongo - elasticsearch # Shared Middleware mongo: image: mongo:5.0 ports: - "27017:27017" volumes: - mongo-data:/data/db redis: image: redis:alpine ports: - "6379:6379" volumes: - redis-data:/data rabbitmq: image: rabbitmq:3-management-alpine ports: - "5672:5672" - "15672:15672" volumes: - rabbitmq-data:/var/lib/rabbitmq elasticsearch: image: elasticsearch:7.17.0 ports: - "9200:9200" environment: - discovery.type=single-node - ES_JAVA_OPTS="-Xms512m -Xmx512m" volumes: - elastic-data:/usr/share/elasticsearch/data # Persistent volumes for data retention volumes: mongo-data: redis-data: rabbitmq-data: elastic-data:
Key tips here:
- Use service names (like
mongo,redis) as hostnames in your Yii configs—Docker Compose automatically creates a network where these names resolve to the correct containers. - The
depends_ondirective ensures services start in the right order (note: it doesn’t wait for a service to be fully ready; for dev, this is usually fine).
Replace your Vagrant commands with Docker equivalents:
- Start the entire stack:
docker-compose up -d - Stop the stack:
docker-compose down - SSH into a service container:
docker exec -it service1-fpm bash - View logs for a service:
docker-compose logs -f service1-fpm - For Xdebug debugging: Install Xdebug in your PHP-FPM image, and set the remote host to
host.docker.internal(Docker Desktop) or your Linux host’s IP address.
When you’re ready to deploy to production:
- Build minimal production images (keep dev dependencies out).
- Use Kubernetes or Docker Swarm for orchestration (better scalability and resilience).
- Implement health checks for all services to ensure they’re running correctly.
- Use secure, persistent storage (cloud volumes instead of local Docker volumes).
- Add monitoring tools like Prometheus + Grafana to track service performance.
- Permission Issues: Always set correct ownership for Yii’s writable directories in your
Dockerfile. - Missing Extensions: Double-check that all PHP extensions your Yii services need are installed and enabled.
- Service Communication: If services can’t talk to each other, verify they’re on the same Docker network (Composer creates this automatically, but typos in service names are a common culprit).
内容的提问来源于stack exchange,提问作者Hussam Jarrah




