Docker Container Setup for 1C-Bitrix: From Chaos to Stability
We often see Bitrix Dockerized with a simple docker-compose up. But stable production operation—with correct restart policies, permissions, log rotation, and seamless updates—is our specialty. Statistics: 90% of help requests involve Bitrix writing files as one user while nginx reads them as another; OPcache not seeing code changes; agents not running due to missing cron inside the container. Let's solve these with practical examples that save up to 40% maintenance time.
Problems Solved by Proper Docker Setup for Bitrix
Without proper configuration, Bitrix containers in production become a headache. Here's what we encounter most:
-
File permissions: files created by different users, causing 403 or 500 errors. Case: a client lost 2 days finding the cause until we set UID via build-arg. UID mapping is 10 times more reliable than manual chmod after every deploy.
-
Downtime during updates: without a rolling update strategy, each release means minutes of unavailability. For an e-commerce store with significant turnover, that's a substantial loss for even a few minutes of downtime.
-
Disk overflow: container logs without rotation grow to 5 GB in a week. While SSD cost is manageable, the risk of failure due to full disk is real.
Setting Up File Permissions in Docker for Bitrix
Classic issue: PHP-FPM inside the container runs as www-data (UID 33), while files on the volume are owned by root or another host user. Bitrix cannot write cache or save uploaded files.
We solve this by explicitly setting UID in Dockerfile:
FROM php:8.1-fpm-alpine
ARG HOST_UID=1000
RUN addgroup -g $HOST_UID bitrix && adduser -u $HOST_UID -G bitrix -D bitrix
RUN sed -i 's/user = www-data/user = bitrix/g' /usr/local/etc/php-fpm.d/www.conf \
&& sed -i 's/group = www-data/group = bitrix/g' /usr/local/etc/php-fpm.d/www.conf
In docker-compose.yml pass the argument:
php-fpm:
build:
context: ./docker/php
args:
HOST_UID: ${HOST_UID:-1000}
Official 1С-Bitrix documentation recommends UID mapping for Docker containers.
Compare: with default www-data you get 403 errors everywhere; with UID mapping—full compatibility with host permissions. For security, we also block access to Bitrix service directories via nginx.
Configuring nginx for Production
server {
listen 80;
server_name _;
root /var/www/html;
index index.php;
charset utf-8;
client_max_body_size 256m;
location ~* /\.ht { deny all; }
location ~* /bitrix/modules { deny all; }
location ~* /bitrix/php_interface { deny all; }
location ~* /bitrix/tools { deny all; }
location ~* \.(jpg|jpeg|png|gif|webp|svg|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
try_files $uri =404;
}
location / {
try_files $uri $uri/ /bitrix/urlrewrite.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
}
location = /bitrix/urlrewrite.php {
fastcgi_pass php-fpm:9000;
fastcgi_param SCRIPT_FILENAME $document_root$$fastcgi_script_name;
include fastcgi_params;
}
}
Healthcheck and Restart Policies
Add a healthcheck to verify container state:
healthcheck:
test: ["CMD-SHELL", "php-fpm -t && kill -0 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
This checks configuration validity and process liveness. As noted in Docker, healthcheck is mandatory for production.
Choose restart policy:
| Policy |
Behavior |
Recommendation |
restart: always |
Always restarts—after crash, Docker restart, even after docker stop. |
For MySQL: ensures DB starts whenever daemon boots. |
restart: unless-stopped |
Restarts after crash and Docker restart, but not after docker stop. |
For nginx and php-fpm: gives control—if stopped manually, there was a reason. |
Comparison of Common Problems and Solutions
| Problem |
Solution |
Effectiveness |
| File permissions |
UID mapping in Dockerfile |
100% elimination of 403 errors |
| Disk overflow |
Log rotation (max-size, max-file) |
Up to 80% disk space savings |
| Downtime during updates |
Rolling update via --no-deps |
Zero-downtime update, 0 seconds downtime |
Why Log Rotation Matters
Without rotation, logs can eat tens of gigabytes in a week. Configure in docker-compose.yml:
services:
nginx:
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
php-fpm:
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
Or globally via /etc/docker/daemon.json. Disk space savings up to 80%.
How to Update Bitrix Containers Without Downtime
Use a strategy updating only php-fpm, leaving nginx untouched:
-
docker-compose pull php-fpm
-
docker-compose up -d --no-deps --build php-fpm
This takes seconds—nginx continues accepting requests and routes them to the old container while the new one starts. For large projects with replicas, update them one by one. Advanced config can achieve 100% uptime during updates.
What's Included in Turnkey Setup
- Configuration of nginx, PHP-FPM, MySQL with platform-specific tuning.
- File permission solution via UID mapping.
- Healthcheck and restart policies for all services.
- Log rotation and backup (database + files).
- Deployment and maintenance documentation.
- 30 days of free support after launch.
Backup Strategy
For reliability, we use a script that dumps the database and archives files. The script runs via host cron and stores backups for the last 7 days.
We will evaluate your project in one business day—no upfront payment. Contact us to discuss details. Order the setup—and forget about container problems.
Problems We Solve
rsync -avz to production on Friday evening, restart php-fpm, and the site returns 502 — local database settings remain in .settings.php. Classic “deployment the old way” turns into a lottery. Another scenario: a module update from the admin panel breaks a custom component template — changes aren’t tracked in version control, recovery takes hours. Without a DevOps culture, every release is a gamble.
We design a predictable DevOps cycle for 1C-Bitrix: from Docker environment to Telegram alerts. Each deployment becomes routine, each incident triggers a context‑rich alert. Below is how we solve real Bitrix team problems — with numbers, tools, and proven configurations.
Why DevOps Is Critical for Bitrix Projects?
Bitrix projects carry specific infrastructure requirements: heavy e‑commerce catalogs, 1C exchange via CommerceML, dozens of agents and events. Without CI/CD and monitoring, every change introduces risk. A single stuck agent can silently break a 1C sync for hours; a manual deployment mistake can cost a client lost orders. We’ve seen teams spend 12 hours per month just on manual deployments and crash recovery — after our CI/CD pipeline, that drops to zero.
CI/CD Pipeline: From Commit to Production Without Hands
Git migration – we move the project from FTP to Git (GitLab, GitHub, Bitbucket). Branch structure: main (production), staging, develop, feature branches. A proper .gitignore for Bitrix is non‑trivial:
/bitrix/cache/
/bitrix/managed_cache/
/bitrix/stack_cache/
/upload/
/bitrix/php_interface/dbconn.php
/bitrix/.settings.php
/bitrix/license_key.php
Miss managed_cache/ → the repository bloats to gigabytes. Forget license_key.php → the key leaks.
CI pipeline – automatically runs PHPStan level 5+, PHP_CodeSniffer with Bitrix standard, PHPUnit for business logic, composer audit, frontend build.
CD pipeline – deploys without human intervention. Merge to staging → deploy to staging. Merge to main → deploy to production (with optional manual confirmation). Zero‑downtime via symlink strategy: new version in a separate folder, current → symlink switches in milliseconds. upload/ lives outside release directories. Healthcheck fails → symlink rolls back automatically. Tools: GitLab CI/CD, GitHub Actions, Deployer (PHP). Deployer’s built‑in recipes for Bitrix handle shared directories and symlink deployment out‑of‑the‑box.
Docker Environment: How We Eliminate “It Works on My Machine”
The Docker environment fixes versions of all components: nginx, PHP, MySQL, Redis. Configuration mirrors production — same PHP modules, same php.ini.
Local development – docker-compose.yml includes nginx + php‑fpm 8.1/8.2 + MySQL 8.0 (or MariaDB 10.6) + Redis + Memcached. New developer: git clone + docker-compose up -d → writes code within 5 minutes. Parallel work on different PHP versions via separate compose files.
Bitrix specifics in Docker:
-
/upload/ mounted as a named volume (not bind mount — permission and speed issues on Windows/Mac).
- Cron jobs (
/bitrix/modules/main/tools/cron_events.php) run via a separate container with supervisord.
- “Proactive Protection” module (
security) blocks requests through reverse proxy — need set_real_ip_from and realip_module.
- Database config (
dbconn.php, .settings.php) set via environment variables, never through a volume with production configs.
Production – multi‑stage Dockerfile (build stage for assets, production stage with lightweight image), Docker Registry for tagged images, orchestration via Docker Swarm or Kubernetes for large projects.
Nginx and PHP‑FPM Configuration for Bitrix Performance
The difference between “site is slow” and 200 ms TTFB lies in configuration. nginx:
-
location blocks for Bitrix handle urlrewrite.php for friendly URLs.
-
/bitrix/admin/ IP‑restricted via allow/deny.
-
expires 30d for static files — CSS, JS, images cached by the browser.
- Brotli compression (15‑20% better than gzip):
brotli on; brotli_comp_level 6;.
- Rate limiting on
/bitrix/tools/ protects against brute force.
- HTTP/2 push for critical resources.
php‑fpm: pm = dynamic. Calculate pm.max_children: (RAM - RAM_other_services) / avg_memory_per_process. For Bitrix, avg is 40–80 MB. OPcache: opcache.memory_consumption=256 (default 128 is insufficient — Bitrix loads thousands of files), opcache.max_accelerated_files=20000, opcache.validate_timestamps=0 in production (reset via cachetool opcache:reset on deployment). php.ini: memory_limit=256M (up to 512M for heavy imports), max_execution_time=60, upload_max_filesize=100M. Slowlog with request_slowlog_timeout=5s catches bottlenecks before users complain.
Monitoring and Logging: What We Track
Infrastructure – Prometheus + Grafana: metrics for CPU, RAM, disk, network, service status. Alerts: CPU > 80% for 5 minutes, free RAM < 500 MB, disk > 85%, php‑fpm queue > 0 (worker shortage). Node Exporter, MySQL Exporter, PHP‑FPM Exporter collect data.
Application – Uptime check every 60 seconds → Telegram alert within a minute of downtime. Response time of key URLs: /, /catalog/, /personal/order/make/. Sentry for PHP errors — structured errors with context. Bitrix agents (b_agent): we check NEXT_EXEC < NOW() - INTERVAL 1 HOUR — a stuck agent silently breaks 1C exchange.
Logging – ELK Stack or Loki + Grafana: nginx access/error, php‑fpm slow log, MySQL slow query log, Bitrix errors. Rotation via logrotate — without it, access.log takes 50 GB after six months.
Backup Strategy and Disaster Recovery
| Component |
Frequency |
Retention |
Method |
| MySQL DB |
Every 6 hours |
30 days |
mysqldump --single-transaction + gzip |
| Files (upload/) |
Daily |
14 days |
rsync incremental |
| Full backup |
Weekly |
60 days |
tar + gpg encryption |
| Server configs |
On change |
In Git |
Ansible playbooks |
Geographic distribution — S3‑compatible storage + separate server in another datacenter. Test restoration monthly — a backup never restored is just an illusion of security. Cron with notifications: if backup fails, alert immediately.
What’s Included in the Service
Our team brings 5+ years of Bitrix DevOps experience (over 50 successful projects) and certified engineers. The service provides:
- DevOps process documentation (deployment scheme, branch policy, infrastructure description)
- Configured CI/CD pipelines (GitLab CI / GitHub Actions) with working triggers
- Docker environment (
docker-compose.yml, Dockerfile, configs)
- Ansible playbooks for server reproduction
- Monitoring (Grafana dashboards, alerts in Telegram / Slack)
- Secured access with role‑based model
- Team training: two sessions on CI/CD, Docker, and deployment
- Support during implementation (two weeks after launch)
Infrastructure‑as‑code with Ansible is 5× faster than manual server configuration and eliminates human errors.
Implementation Process and Timelines
-
Audit of current state – assess infrastructure, software, processes (2–3 days).
-
Architecture design – choose stack (Docker / K8s / Ansible), agree on CI/CD policies, set up repository.
-
Environment setup – Docker for local development, staging, production servers.
-
CI/CD implementation – write pipelines, test deployment, integrate with monitoring.
-
Monitoring and alerting – install Prometheus + Grafana, configure dashboards and notifications.
-
Team training – two sessions on tool usage.
| Task |
Duration |
| Docker environment for local development |
2–3 days |
| CI/CD pipeline (GitLab CI / GitHub Actions) |
1–2 weeks |
| Staging environment |
3–5 days |
| Monitoring + alerting (Prometheus + Grafana) |
1–2 weeks |
| Centralized logging (ELK / Loki) |
1–2 weeks |
| Ansible server automation |
2–3 weeks |
| Comprehensive DevOps implementation |
4–8 weeks |
DevOps is not a project with an end date — it’s a transition from “upload via FTP and pray” to predictable processes. Each deployment is routine, each incident carries context, each new developer does docker-compose up instead of a three‑day environment setup.
Get a consultation – we’ll prepare a tailored implementation plan within 2–3 days. Order a turnkey DevOps implementation – gain stability and full control over your infrastructure.