ProFor.Pro Profor.Pro
profor.pro / notes / 1c-docker-linux-2026
1C Linux 5 min read

Running 1C on Docker under Linux in 2026: a setup that survives upgrades

A pragmatic recipe for running 1C:Enterprise server inside Docker on Linux, with persistent volumes, PostgreSQL tuning, and an upgrade flow that does not break ragent on platform bumps.

We have been running 1C:Enterprise on Linux containers for several years now. Every time the platform version bumps, somebody on the team rediscovers why the official tarball plus a hand-written systemd unit is a bad idea. This post is the layout we settled on: one image per platform version, a stable data volume, a separate PostgreSQL container, and a cluster registry that survives docker compose down -v mistakes.

Nothing here is exotic. The point is that the moving parts are small enough that a junior engineer can rebuild the stack from scratch in an hour.

What we are actually deploying

Three containers, one network, two volumes:

  • onec-serverragent, rmngr, rphost processes from the platform tarball.
  • onec-pg — PostgreSQL build patched for 1C (the standard fork from PostgresPro or the community patches, depending on what your license allows).
  • onec-ws — optional Apache or nginx in front of the web publication, only if you publish bases over HTTP.

Volumes:

  • onec-srvinfo — the cluster registry under /home/usr1cv8/.1cv8/1C/1cv8/srvinfo. This is the volume you must never lose. It holds cluster topology, infobase list, security settings.
  • onec-pgdata — Postgres data directory. Same rules as any other Postgres deployment.

The image: pinned, not floating

We build one image per platform version and tag it explicitly. No latest. The platform installer tarball goes in by build arg, so the Dockerfile is the same for every version.

FROM debian:12-slim

ARG ONEC_VERSION
ARG ONEC_TARBALL=server64_${ONEC_VERSION}.tar.gz

RUN apt-get update && apt-get install -y --no-install-recommends \
    imagemagick libfreetype6 libgsf-1-114 libglib2.0-0 \
    libwebkit2gtk-4.0-37 fonts-liberation ttf-mscorefonts-installer \
    locales tzdata ca-certificates curl && \
    sed -i '/ru_RU.UTF-8/s/^# //' /etc/locale.gen && locale-gen && \
    rm -rf /var/lib/apt/lists/*

ENV LANG=ru_RU.UTF-8 LC_ALL=ru_RU.UTF-8

COPY ${ONEC_TARBALL} /tmp/
RUN mkdir /tmp/onec && tar -xzf /tmp/${ONEC_TARBALL} -C /tmp/onec && \
    cd /tmp/onec && ./setup-full-${ONEC_VERSION}-x86_64.run --mode unattended && \
    rm -rf /tmp/onec /tmp/${ONEC_TARBALL}

USER usr1cv8
WORKDIR /home/usr1cv8
EXPOSE 1540 1541 1560-1591
CMD ["/opt/1cv8/x86_64/current/ragent", "-daemon"]

Build it like this:

docker build \
  --build-arg ONEC_VERSION=8.3.24.1234 \
  -t registry.local/onec:8.3.24.1234 .

Do not bake the platform tarball into a public registry. The license is per-customer; treat the image as a private artifact.

Compose file

services:
  onec-pg:
    image: registry.local/postgres-1c:15
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/pg_password
      POSTGRES_DB: postgres
      TZ: Europe/Belgrade
    volumes:
      - onec-pgdata:/var/lib/postgresql/data
    secrets: [pg_password]
    shm_size: 1g
    networks: [onec]

  onec-server:
    image: registry.local/onec:8.3.24.1234
    depends_on: [onec-pg]
    volumes:
      - onec-srvinfo:/home/usr1cv8/.1cv8/1C/1cv8/srvinfo
    ports:
      - "1540:1540"
      - "1541:1541"
      - "1560-1591:1560-1591"
    networks: [onec]
    restart: unless-stopped

volumes:
  onec-pgdata:
  onec-srvinfo:

networks:
  onec:

secrets:
  pg_password:
    file: ./secrets/pg_password

The port range 1560-1591 is what rphost workers grab. If you constrain it, rphost will silently refuse to start more workers under load.

PostgreSQL: the boring part that breaks first

A generic Postgres tune is fine for small infobases. Anything above a few dozen GB needs the usual treatment:

  • shared_buffers ~ 25% of container RAM.
  • work_mem ~ 64–128 MB. 1C generates a lot of small sorts.
  • max_connections ~ 200–500. 1C opens connections aggressively.
  • effective_cache_size ~ 60–70% of RAM.
  • Disable huge_pages unless you actually configured them on the host.
  • temp_file_limit set high. Reposting documents on a closed period will write GB of temp.

Mount postgresql.conf as a separate file so you can change it without rebuilding the image:

    volumes:
      - onec-pgdata:/var/lib/postgresql/data
      - ./pg/postgresql.conf:/etc/postgresql/postgresql.conf:ro
    command: postgres -c config_file=/etc/postgresql/postgresql.conf

The upgrade flow

This is the part that bites teams who never wrote it down. The platform version is upgraded much more often than the configuration. We follow a fixed sequence:

  1. Build and push the new image: registry.local/onec:8.3.25.xxxx.
  2. Stop user sessions through the cluster console (or rac session terminate).
  3. Take a pg_dump of every infobase. Yes, a filesystem snapshot of onec-pgdata is faster, but a logical dump is what you actually want when something goes wrong with 1C-specific catalog bits.
  4. docker compose down for the onec-server service only. Postgres stays up.
  5. Update the image tag in compose.yaml, docker compose up -d onec-server.
  6. Watch docker logs -f onec-server. The first start on a new platform version rewrites parts of srvinfo. If it crashes here, do not restart in a loop — investigate.
  7. Open each infobase in Designer to let it apply the platform-level migrations. This step cannot be skipped on major bumps.

Because srvinfo lives in a named volume and the image is immutable, rolling back is docker compose up -d onec-server with the previous tag. The cluster registry is forward-and-backward compatible across minor versions, less so across major ones — keep the dump.

If you publish bases over HTTP, the web extension version must match the platform version. We rebuild the onec-ws image in the same CI job to keep them in lockstep.

Things we learned the hard way

  • Locales matter. A container without ru_RU.UTF-8 will start ragent and then mangle every string from the infobase. Generate the locale at build time.
  • shm_size on Postgres. The default 64 MB is enough to make parallel queries fail with a generic shared memory error. Bump it.
  • Do not bind-mount srvinfo from the host onto Linux with weird permissions. The usr1cv8 UID inside the container will be different from your host user, and ragent will silently store nothing. Use a named volume.
  • rphost memory limits. Set --memory on the container generously, then use cluster-level rphost recycling instead of letting the OOM killer end your day.
  • Time zone. If the container TZ does not match what 1C expects, posting documents around midnight produces date-shifted entries. Set TZ explicitly in both containers.

What we would change next

We are slowly moving the cluster onto Kubernetes with a StatefulSet for onec-server and an external managed Postgres. The image and the volume layout above port over without changes — which is the entire point of keeping the Compose setup boring. If the upgrade ritual fits on one page of a runbook, the platform team can ship a new 1C version on a Friday afternoon without anyone losing sleep. Almost.