Docker environment for 1C-Bitrix: PHP 8.1, Xdebug, MySQL, Redis

Developers and testers work on different machines, and version discrepancies surface only on the production site. We set up a unified development environment turnkey: identical settings for the whole team, fast project launch on a new machine, and predictable results. This eliminates a whole class of errors and reduces the time needed to onboard new people into the project.

Our competencies:

Frequently Asked Questions

Setting Up a Development Environment for a Bitrix Project

A change that passes all checks on an engineer's machine can bring down the catalog or checkout after being transferred to the production server.

The cause is almost always the same: different versions of the platform and dependencies run locally and in production, caching settings and database connection parameters differ.

The code is the same, the behavior is different — and you have to figure it out at the moment when the site is already unavailable to users.

A mismatch between local and production versions is not a minor thing. The database driver returns data as one type on one side and another type on the other; cache is configured for different stores; extensions are built with different flags.

Add dependencies installed manually and not pinned in the manifest — and you get an irreproducible build that cannot be repeated one-to-one even on the laptop next door.

A separate category is manual steps. Someone installed a module through the admin panel, someone tweaked the server config on the fly, someone cleared the cache with the wrong script.

These actions are not recorded anywhere, so a new machine is assembled differently, and errors after deploying changes are searched through logs blindly.

Setting up a development environment solves this at the reproducibility level: the same set of services, pinned dependency versions, unified database and cache parameters, the same set of extensions, and debug mode. Then deploying changes stops being an event with risk.

We explain how this is arranged in a Bitrix project and why it pays off on the very first disputed change.

What Changes in the Team's Work After Container Adoption

A single image removes the main source of mismatches: the PHP extension set, MySQL parameters, Redis and queue configuration are described in one file and are the same for everyone — on an engineer's laptop, in staging, and in production.

The project comes up with one command, not according to an internal instruction that was outdated two changes ago.

The time for a new engineer to join the project is reduced from one or two days to two or three hours: no need to assemble a local environment manually, catch version conflicts, and wait for a senior to free up.

Docker here is not an end in itself — it gives the same result on any machine, and that is exactly what the team checks on the first task.

The share of builds that pass without on-the-spot edits grows: the typical scenario now is that the code assembled and ran as is, without tweaks in staging.

At the same time, a whole class of failures due to environment mismatches goes away: behavior is determined by configuration, not by someone forgetting to install an extension or changing a server setting.

Rollback speeds up to minutes: the previous environment version is pinned and comes up by switching to the prior tag — without investigating what and when changed on the production machine.

Environment Options: Containers, Shared Server, Manual Assembly

Containerization, shared test staging, and local assembly solve one task in different ways: give an engineer a workspace where code runs predictably.

The choice is influenced by the number of projects, release frequency, and how painful the mismatch between the developer's environment and production is.

Option When suitable Limitations
Isolated containers Multiple projects and parallel tasks, need the same environment for the whole team Requires a build description and image maintenance, higher entry threshold for a new engineer
Shared test staging One large project, long branches, need a live demo for the client Developer changes interfere with each other, database state cannot be reset to clean with one action
Local manual assembly One-off tasks, debugging bottlenecks, work without access to an external server Version and setting mismatches between machines, long onboarding, "works on my machine"
Hybrid environment Services in containers, while code and debugging are on the engineer's machine Need to synchronize configuration between parts and maintain a common settings layer

Most often, teams settle on a hybrid scheme: dependency isolation is covered by containers, while the familiar work pace and debugger breakpoints remain. Next — how this transition is done without stopping current tasks.

Implementation Stages: From Repository Audit to Handover to the Team

We start not by launching containers but with inventory: until it is clear which extensions the code needs, where migrations are, and which external services it calls, any image build turns into rework. That is why we do the work in stages.

  1. Dependency audit. We pin versions of PHP, MySQL, and Redis, the list of extensions, packages with native builds, cron scripts, and external API calls. The output is a map: what comes up in the environments, what remains outside.
  2. Environment scheme. We determine the service composition, volumes for the database and uploaded files, network, environment variables, and the method of secret injection. We agree on the scheme before the first line of configuration.
  3. Image builds. We build reproducible images of the application and services, cache layers, and pin base images by checksum — engineers and staging get an identical environment.
  4. Debugging and cache. We enable Xdebug in on-demand mode, configure port forwarding, opcache, and Redis. We check that the debugger does not slow regular requests.
  5. Acceptance scenarios. We run real scenarios: clean install, database dump deployment, migrations, email sending, 1C exchange. We consider the environment ready if it passes these checks on a clean machine.
  6. Handover to the team. We give the repository with configuration, the command set, the policy for updating base images, and a walkthrough with developers and support.

Then the environment lives as a repository artifact: changes go through review rather than settling in the local settings of an individual engineer.

What Remains in the Repository and Documentation After the Work

The work ends not with staging that lives on one machine, but with a reproducible set of artifacts in the repository. A new engineer deploys the environment with one command and gets the same behavior as in the test environment and production.

  • Environment configuration: service description files — web, database, cache, queues — with pinned base images and health checks, so the startup order does not depend on luck.
  • Environment variables: hosts, credentials, and modes are moved outside; the repository contains a sample file with an explanation for each variable, and secrets are injected from storage and do not get into history.
  • Startup scripts: a single set of commands for starting, stopping, rebuilding, loading a dump, and executing console tasks — the same for everyone in the team.
  • Access policies: rights for volumes, network segments, and database roles, so the developer does not work as a superuser.
  • Documentation for engineers: service map, entry points, request flow diagram, and a breakdown of typical failures with their symptoms.
  • Update policy: frequency of image rebuilds and dependency compatibility checks, rollback criteria, and a separate branch for test runs.
  • Debug profile: a mode enabled by a flag with breakpoints and profiling — it does not slow regular work and requires no code edits.

Such a set allows returning to the project six months later and bringing up staging without reconstructing details from chat.

Case Study: How a Project Stopped Chasing Version Mismatches

Before: Manual Assembly and Version Mismatches

A project on 1C-Bitrix had a distributed team: some engineers worked locally, some on shared test staging. PHP, MySQL, and Redis versions on the machines diverged, so cache and extension behavior differed from staging.

A new engineer raised the environment manually — up to three hours, and another same amount was spent reconciling with colleagues' configuration.

Version mismatches surfaced at acceptance: the task passed locally and failed in staging. Investigating one case took two to eight hours — they compared module versions, php.ini parameters, and MySQL settings manually, because there was no single source of configuration.

After: Environment as Code

We described the environment as a set of configurations: images with pinned major versions of PHP, MySQL, and Redis, a shared Xdebug profile, and a single extension list.

Debug mode is enabled by a variable — locally debugging is active, in staging it is disabled, while the build is the same.

Metric Before After
Environment setup by a new engineer up to 3 hours manually one launch, about 15 minutes
Version mismatch investigation 2–8 hours per case does not occur
Build and test run manually on the machine automatically in a single image

The team transition took several weeks and proceeded without stopping current tasks. Build time decreased from hours to one launch, and the class of failures "works on my machine" stopped appearing in the tracker.

What to Do If a Shared Test Server Is Already Deployed

Shared staging lives its own life: language and extension versions on the host have long diverged from what is documented, the database is shared by all teams, and test scenario data overwrites each other.

No one is going to decommission it — staging hosts client demos, integration acceptance, and debugging. Therefore we examine three paths for integrating a container environment into an already deployed staging without stopping team work.

The work order is common: first inventory — which services, volumes, rights, and external systems are tied to staging. Then an image is built that comes up locally for each engineer, and only after that is staging switched service by service.

Mixed schemes are kept on a shared database volume and external cache, otherwise data diverges between the container and the host. Transition risks are covered by a replacement plan: for each service — a rollback point and a criterion by which we return to the previous launch.

The selection criterion is simple. If the mismatch "works on my machine but not on test" surfaces less than once a quarter — it is enough to supplement new projects with containers.

If constantly — phased migration is needed, and it is worth starting with the most conflicted service: environment setup for a new engineer is reduced from days to minutes.

Environment Questions Asked Before Kickoff

Before kickoff, the team usually brings the same doubts: how to update dependencies without breaking the working site, how the environment coexists with external services, where to debug code inside isolation, and in what order to move to the new scheme.

Below are the answers we discuss at the assessment stage so that the scope of work is clear in advance.

Will updating dependencies break the current site?

Versions are pinned in the image description, not pulled on the fly, so the update goes in a separate branch: build an image with new versions, run the test suite and key user scenarios on a database copy, and only then switch the environment.

Rollback is a return to the previous tag; it remains in the registry. Transition to the new scheme goes in order: first the local environment of one developer, then the shared scheme for the team, then test staging replicating production, and only then production itself. Update stops being an event with downtime.

What about external services — payments, mailings, 1C exchange?

Integrations are connected through vendors' test environments, and for unavailable ones — through local stubs with the same request and response formats. 1C exchange during development goes to a separate database copy, so test documents do not end up in production.

The developer sees real integration behavior but does not depend on external environment availability.

Is debugging inside isolation even possible?

Yes: the step debugger is enabled inside the container, and its port is forwarded only to the developer's machine, so breakpoints work without changes to shared staging. Profiling is enabled on demand — it shows which database and external service requests consume response time.

For 1C-Bitrix this scheme gives the same code behavior on all machines: "works on my machine" mismatch stops being an argument in discussion.

Let's Discuss the Task: What We Need from You to Start Work

To come back with an estimate and work plan, not with clarifying questions, one message with project inputs is enough for us.

The environment composition is determined by the task: the set of services, integration points, and access requirements directly affect both the build structure and the setup timeline.

  • A link to the repository and branch from which we count: the structure shows the build method, whether ready configurations already exist or only local instructions in the README.
  • A description of services that should come up with the project: web server, PHP, database, cache, queues, search — with a note on which are external and which we deploy as containers.
  • A list of projects, if one repository contains several sites or editions: this affects the shared volume scheme and startup order.
  • Access requirements: what should be accessible from outside, whether tunnels to test databases are needed, whether corporate network and security policies have restrictions.
  • A list of dependencies outside the package manager: PHP extensions, binary utilities, modules for 1C exchange.
  • A database dump or sample data, if debugging runs on real scenarios — reproducibility is more important than first launch speed.
  • Contact of the engineer responsible for the project: one conversation removes more questions than correspondence.

Describe the task in a convenient way — by link, email, or message. We will come back with an estimate and work plan: environment composition, stages, timelines, and what will be required on your side at each step.