О насБлогКонтакты
DevOps14 мая 2016 г. 4 мин 14

Как настроить Docker для PHP-разработки в команде: опыт Бишкека (2016)

AunimedaAunimeda
📋 Содержание

Как настроить Docker для PHP-разработки в команде: опыт Бишкека (2016)

Коротко: docker-compose.yml с сервисами nginx:1.10, php:7.0-fpm, mysql:5.7, redis:3.2. Маунтинг кода как volume. docker-compose up -d — и всё работает идентично у всех членов команды. На слабом интернете (что актуально для Кыргызстана): кэшируйте образы локально, используйте .dockerignore для ускорения сборки.


Проблема до Docker

Наша команда из 4 разработчиков в Бишкеке:

  • Разработчик 1: MacBook, MAMP, PHP 5.6
  • Разработчик 2: Ubuntu, установленный PHP 7.0 вручную
  • Разработчик 3: Windows, XAMPP, PHP 7.1
  • Разработчик 4: Ubuntu, OpenServer

Результат: «У меня работает» несколько раз в месяц. Особенно с кодировкой (UTF-8 vs windows-1251 в XAMPP) и версиями PHP.


docker-compose.yml

# docker-compose.yml
version: '2'

services:
  nginx:
    image: nginx:1.10-alpine
    container_name: project_nginx
    ports:
      - "80:80"
    volumes:
      - .:/var/www/html:cached
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - php
    networks:
      - app

  php:
    build:
      context: ./docker/php
      dockerfile: Dockerfile
    container_name: project_php
    volumes:
      - .:/var/www/html:cached
    environment:
      APP_ENV:     local
      APP_DEBUG:   "true"
      DB_HOST:     mysql
      DB_PORT:     3306
      DB_DATABASE: myproject
      DB_USERNAME: myproject_user
      DB_PASSWORD: secret
      REDIS_HOST:  redis
    depends_on:
      - mysql
      - redis
    networks:
      - app

  mysql:
    image: mysql:5.7
    container_name: project_mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: rootsecret
      MYSQL_DATABASE:      myproject
      MYSQL_USER:          myproject_user
      MYSQL_PASSWORD:      secret
    volumes:
      - mysql_data:/var/lib/mysql
      - ./docker/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    command: >
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci
      --innodb-buffer-pool-size=256M
    networks:
      - app

  redis:
    image: redis:3.2-alpine
    container_name: project_redis
    networks:
      - app

networks:
  app:
    driver: bridge

volumes:
  mysql_data:

docker/php/Dockerfile

FROM php:7.0-fpm

# Системные зависимости
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    libmcrypt-dev \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    && rm -rf /var/lib/apt/lists/*

# PHP расширения
RUN docker-php-ext-configure gd --with-freetype-dir=/usr --with-jpeg-dir=/usr \
    && docker-php-ext-install \
       pdo \
       pdo_mysql \
       mbstring \
       gd \
       opcache \
       mcrypt \
       zip

# Redis расширение
RUN pecl install redis-3.0.0 \
    && docker-php-ext-enable redis

# Composer
COPY --from=composer:1 /usr/bin/composer /usr/bin/composer

# PHP конфигурация для разработки
COPY php-dev.ini /usr/local/etc/php/conf.d/90-custom.ini

RUN useradd -u 1000 -m developer
USER developer

WORKDIR /var/www/html

docker/php/php-dev.ini

; Разработческие настройки
error_reporting         = E_ALL
display_errors          = On
log_errors              = On
error_log               = /dev/stderr

memory_limit            = 256M
max_execution_time      = 120
upload_max_filesize     = 50M
post_max_size           = 50M

; Часовой пояс: Бишкек
date.timezone           = Asia/Bishkek

; OPcache: проверять изменения файлов каждые 0 секунд (разработка)
opcache.enable          = 1
opcache.revalidate_freq = 0
opcache.validate_timestamps = 1
opcache.memory_consumption  = 128

; mbstring: UTF-8 по умолчанию
mbstring.internal_encoding = UTF-8
mbstring.language           = Russian

docker/nginx/default.conf

server {
    listen 80;
    server_name localhost;
    root /var/www/html/public;
    index index.php index.html;
    
    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  HTTPS off;
        include        fastcgi_params;
    }

    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2)$ {
        expires 1d;
        access_log off;
    }

    location ~ /\. {
        deny all;
    }

    # Увеличить лимит загрузки для файлов
    client_max_body_size 50M;
}

.dockerignore для медленного интернета

# .dockerignore — исключить из Docker build context
# Критично при медленном интернете (скорость сборки)
.git
.gitignore
node_modules
vendor
storage/logs
storage/framework/cache
*.log
.env
.env.*
tests/
docs/
*.md

Makefile для удобства

# Makefile — короткие команды вместо длинных docker-compose ...

up:
	docker-compose up -d

down:
	docker-compose down

restart:
	docker-compose restart

bash:
	docker-compose exec php bash

artisan:
	docker-compose exec php php artisan $(filter-out $@,$(MAKECMDGOALS))

composer:
	docker-compose exec php composer $(filter-out $@,$(MAKECMDGOALS))

mysql:
	docker-compose exec mysql mysql -u myproject_user -psecret myproject

logs:
	docker-compose logs -f --tail=100

build:
	docker-compose build --no-cache php

test:
	docker-compose exec php php artisan test

migrate:
	docker-compose exec php php artisan migrate

seed:
	docker-compose exec php php artisan db:seed

.PHONY: up down restart bash artisan composer mysql logs build test migrate seed
# Использование:
make up
make bash
make artisan migrate
make artisan make:model Product
make composer require predis/predis

Решение проблемы с медленным скачиванием образов

# Проблема: в Бишкеке в 2016 скачать образ MySQL 5.7 (370 МБ) занимало 20–40 минут
# Решение: скачать образы один раз, перенести на флешке

# На компьютере с быстрым интернетом:
docker pull nginx:1.10-alpine
docker pull php:7.0-fpm
docker pull mysql:5.7
docker pull redis:3.2-alpine

# Сохранить в архив
docker save nginx:1.10-alpine php:7.0-fpm mysql:5.7 redis:3.2-alpine | gzip > docker-images.tar.gz
# ~640 МБ

# Перенести на флешке на другой компьютер:
docker load < docker-images.tar.gz

# Теперь docker-compose up не скачивает ничего

Результат после перехода на Docker

Через 2 месяца:

  • Количество «у меня не работает» инцидентов: 4/месяц → 0
  • Время онбординга нового разработчика: 4–6 часов → 45 минут
  • Разница окружений между dev и prod: исчезла
  • Случайные баги «только на Windows»: исчезли

Главный вывод: Docker в небольшой команде окупается за первый же месяц, даже если скорость интернета затрудняет первоначальную загрузку образов.

Читайте также

Хостинг для сайта в Кыргызстане: VPS, shared или облако - что выбрать в 2026aunimeda
DevOps

Хостинг для сайта в Кыргызстане: VPS, shared или облако - что выбрать в 2026

Разбираем типы хостинга для сайтов в Кыргызстане: shared, VPS, облачный и выделенный сервер. Реальные цены в сомах, рейтинг провайдеров и когда стоит апгрейдиться.

Docker и CI/CD для небольшой команды: что мы реально запускаем в продакшенеaunimeda
DevOps

Docker и CI/CD для небольшой команды: что мы реально запускаем в продакшене

Kubernetes - не для всех. Наш продакшен-стек для 6 проектов командой из 8 человек: Docker Compose, GitHub Actions, Nginx - без Kubernetes и без $800/месяц на AWS.

Как настроить HTTPS на nginx в 2015 году: от покупки сертификата до A+ на SSL Labsaunimeda
DevOps

Как настроить HTTPS на nginx в 2015 году: от покупки сертификата до A+ на SSL Labs

В 2015 году Let's Encrypt ещё не вышел. HTTPS стоил денег и требовал ручной настройки. Мы прошли путь от покупки сертификата за $10 до рейтинга A+ на SSL Labs для сервисов наших бишкекских клиентов. Конфигурация nginx, цепочка сертификатов, HSTS — точный рабочий конфиг.

Нужна IT-разработка для вашего бизнеса?

Разрабатываем сайты, мобильные приложения и AI-решения для бизнеса в Кыргызстане. Бесплатная консультация.

Получить консультацию Все статьи