Skip to main content
This topic describes how to run ABBYY FineReader Engine 12 inside Docker containers on Linux. There are two setup options covered in this topic:
OptionDescription
Single containerLicensing Service and FRE worker packaged together.

Simpler; good for testing, demos, and single-shot OCR jobs.
Two containersLicensing Service and FRE worker in separate containers.

Better fault tolerance; if one crashes, it can restart without interrupting the other. Multiple workers can share one Licensing Service.
Both setup options support Online Licenses and Local Licenses, and both build on ubuntu:noble (24.04 LTS).

License types

FRE 12 accepts two types of licenses: Online and Local. Both types work in both single-container and two-container setups, but they have different activation and runtime requirements.

Online license

  • Filename pattern: XXXXXXXXXXXXXXXXXXXX.ABBYY.ActivationToken
  • Validates against *.abbyy.com at runtime — every container run needs internet access.
  • Requirements wherever the Licensing Service is installed:
    • Active internet connection
    • Allowed outbound HTTPS (port 443) to *.abbyy.com
    • GoDaddy Trusted Root CA in the system ca-certificates package (already present in ubuntu:noble)
  • Single Licensing Service instance can work with only one Online License at a time.

Local license

  • Filename pattern: XXXX-XXXX-XXXX-XXXX-XXXX-XXXX.ABBYY.LocalLicense
  • Activated at build time during FRE installation, then embedded in the image.
  • Internet not required at runtime — good for air-gapped environments.

Getting started

To use either set-up option in this guide, you will need:
  • Docker and Docker Compose installed (docker compose v2 syntax)
  • ABBYY FineReader Engine 12 Linux installer: FRE*.sh
  • License file (.ABBYY.ActivationToken or .ABBYY.LocalLicense) and password

Setup option 1 — Single container

This option runs the Licensing Service and the FRE worker in one container. The entrypoint starts the Licensing Service in the background, waits briefly for it to come up, runs the CLI sample, prints the output, and cleanly shuts down all processes on exit.Recommended for local testing, demos, and CI jobs where you just want one command to start and stop.

Files

Create an empty directory and add the following files:
  • Dockerfile — builds the combined image (listed below)
  • entrypoint.sh — starts the LS, runs the CLI sample, prints the result (listed below)
  • docker-compose.yml — builds and runs the container (listed below)
  • .env — holds your license filename and password (listed below)

Build and run

  1. Copy your FRE*.sh installer and license file into the directory you created above.
  2. Create a .env file with your license values (see below).
  3. From that directory, run the following command to build the image and start the container:
    docker compose up
    
The CLI sample will processes the bundled Demo.tif using OCR and prints the recognized text to the console.

.env

# For a Local License:
LICENSE_FILE=XXXX-XXXX-XXXX-XXXX-XXXX-XXXX.ABBYY.LocalLicense
# For an Online License:
# LICENSE_FILE=XXXXXXXXXXXXXXXXXXXX.ABBYY.ActivationToken
LICENSE_PASSWORD=your_password_here

docker-compose.yml

services:
  fre:
    build:
      context: .
      args:
        - license_file=${LICENSE_FILE}
        - license_password=${LICENSE_PASSWORD}
    shm_size: 1g
    command: ["-if /app/Demo.tif -f TextUnicodeDefaults -of /app/Test.txt"]
shm_size: 1g is required. FRE uses POSIX shared memory and the default 64MB /dev/shm is not enough. Do not remove or change this setting.

Dockerfile

This is a two-stage build:
  • Stage 1 uses gcc:8 to install FRE and compile the CLI sample.
  • Stage 2 creates a minimal ubuntu:noble runtime image and copies in the Licensing Service binaries, the FRE runtime, the compiled sample, and the license file.
# Stage 1: Install FRE and compile the CLI sample
FROM gcc:8 AS builder

ARG license_file
ARG license_password

COPY ${license_file} /tmp/${license_file}
COPY FRE*.sh /tmp/FRE12.sh

RUN chmod +x /tmp/FRE12.sh && /tmp/FRE12.sh -- \
    --install-dir "/opt/ABBYY/FREngine12" \
    --license-path "/tmp/${license_file}" \
    --license-password "${license_password}" \
    --developer-install

WORKDIR /opt/ABBYY/FREngine12/Samples/CommandLineInterface
RUN make

# Remove developer-only library (not needed at runtime)
RUN rm /opt/ABBYY/FREngine12/Bin/libProtection.Developer.so

# Stage 2: Minimal runtime image with both Licensing Service and FRE
FROM ubuntu:noble

RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
    apt-get install --no-install-recommends -y \
    ca-certificates bash libc6 libglib2.0-0 libgcc-s1 libstdc++6 \
    zlib1g libx11-6 libfreetype6 libxext-dev libice-dev libsm-dev \
    locales && \
    locale-gen en_US.UTF-8 && \
    rm -rf /var/lib/apt/lists/*

# Copy Licensing Service
COPY --from=builder /usr/local/bin/ABBYY/SDK/12/Licensing /usr/local/bin/ABBYY/SDK/12/Licensing/
COPY --from=builder /usr/local/lib/ABBYY/SDK/12/Licensing /usr/local/lib/ABBYY/SDK/12/Licensing/

# Copy FRE runtime binaries and data
COPY --from=builder /opt/ABBYY/FREngine12/Bin /opt/ABBYY/FREngine12/Bin
COPY --from=builder /opt/ABBYY/FREngine12/Data /opt/ABBYY/FREngine12/Data

# Copy license file (works for both .ActivationToken and .LocalLicense)
COPY --from=builder /var/lib/ABBYY/SDK/12/Licenses/*.ABBYY.* /var/lib/ABBYY/SDK/12/Licenses/

# Copy compiled CLI sample and demo image
COPY --from=builder /opt/ABBYY/FREngine12/Samples/CommandLineInterface/CommandLineInterface /app/
COPY --from=builder /opt/ABBYY/FREngine12/Samples/SampleImages/Demo.tif /app/

# Create license working directory
RUN mkdir -p /var/lib/ABBYY/SDK/12/Licenses && chmod 755 /var/lib/ABBYY/SDK/12/Licenses

ENV LD_LIBRARY_PATH=/opt/ABBYY/FREngine12/Bin:/usr/local/lib/ABBYY/SDK/12/Licensing
ENV LANG=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

#!/bin/bash

# Start the Licensing Service in the background
/usr/local/bin/ABBYY/SDK/12/Licensing/LicensingService /standalone &
LS_PID=$!

# Wait for the Licensing Service to be ready
sleep 2

# Run the CLI sample
/app/CommandLineInterface $1

status=$?
if [ $status -ne 0 ]; then
  echo "Failed to launch app: $status"
  kill $LS_PID 2>/dev/null
  exit $status
fi

# Display the output file contents
cat ${1##*-of}
echo "Done"

# Clean up
kill $LS_PID 2>/dev/null

Setup option 2 — Two containers

This option runs the Licensing Service and the FRE worker in separate containers on a shared Docker Compose network. The worker communicates with the Licensing Service over TCP at ls:3023.Recommended for production deployments. Running the services in separate containers means Docker can restart either one independently if it crashes. It also allows multiple workers to connect to the same Licensing Service.
Do not run multiple worker replicas against a single Licensing Service unless your license permits it. A single Licensing Service instance supports only one Online License at a time.

Files

Create an empty directory and add the following files:
  • Dockerfile_ls — builds the Licensing Service container (listed below)
  • Dockerfile_worker — builds the FRE worker container (listed below)
  • entrypoint.sh — runs the CLI sample in the worker (listed below)
  • docker-compose.yml — wires the two containers together (listed below)
  • .env — holds your license filename and password (same format as Setup 1)

Build and run

  1. Copy your FRE*.sh installer and license file into the directory.
  2. Create a .env file with your license values.
  3. From that directory, run:
    docker compose up
    
Both containers are built and started. The Licensing Service starts first, followed by the worker, which runs the CLI sample against the bundled Demo.tif and prints the result.

docker-compose.yml

services:
  ls:
    build:
      context: .
      dockerfile: Dockerfile_ls
    restart: on-failure

  worker:
    build:
      context: .
      dockerfile: Dockerfile_worker
      args:
        - license_file=${LICENSE_FILE}
        - license_password=${LICENSE_PASSWORD}
        - service_address=ls:3023
    depends_on:
      - ls
    shm_size: 1g
    command: ["-if /app/Demo.tif -f TextUnicodeDefaults -of /app/Test.txt"]
    restart: on-failure
A few things to notice:
  • The worker uses depends_on: [ls] so the Licensing Service container will start first.
  • Both services use restart: on-failure allowing them to come back independently.
  • The worker’s service_address build argument is ls:3023 — Docker Compose’s built-in DNS resolves ls to the Licensing Service container.
  • shm_size: 1g is configured on the worker, not the Licensing Service because FRE requires shared memory.

Dockerfile_ls

This is a two-stage build:
  • Stage 1 runs the FRE installer with --skip-local-license-activation to extract the Licensing Service binaries.
  • Stage 2 creates a minimal ubuntu:noble runtime image, exposes port 3023, and runs LicensingService /standalone as PID 1. The /standalone flag keeps the Licensing Service in the foreground, which is the right approach in Docker (a foreground process logs to stdout and exits cleanly when the container is stopped).
# Stage 1: Extract Licensing Service from FRE installer
FROM ubuntu:noble AS builder

RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
    apt-get install --no-install-recommends -y \
    bash gzip tar coreutils gettext-base && \
    rm -rf /var/lib/apt/lists/*

COPY FRE*.sh /tmp/FRE12.sh

RUN chmod +x /tmp/FRE12.sh && /tmp/FRE12.sh -- \
    --install-dir "/opt/ABBYY/FREngine12" \
    --skip-local-license-activation

# Stage 2: Minimal runtime for the Licensing Service
FROM ubuntu:noble

RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
    apt-get install --no-install-recommends -y \
    ca-certificates bash libc6 libgcc-s1 libstdc++6 && \
    rm -rf /var/lib/apt/lists/*

COPY --from=builder /usr/local/bin/ABBYY/SDK/12/Licensing /usr/local/bin/ABBYY/SDK/12/Licensing/
COPY --from=builder /usr/local/lib/ABBYY/SDK/12/Licensing /usr/local/lib/ABBYY/SDK/12/Licensing/

RUN mkdir -p /var/lib/ABBYY/SDK/12/Licenses && chmod 755 /var/lib/ABBYY/SDK/12/Licenses

ENV LD_LIBRARY_PATH=/usr/local/lib/ABBYY/SDK/12/Licensing

EXPOSE 3023

ENTRYPOINT ["/usr/local/bin/ABBYY/SDK/12/Licensing/LicensingService", "/standalone"]

Dockerfile_worker

This is a two-stage build:
  • Stage 1 installs FRE with --developer-install and --service-address pointing at the Licensing Service container, then compiles the CLI sample.
  • Stage 2 creates a minimal ubuntu:noble runtime image containing only the FRE binaries, the compiled sample, and the demo image. Because the worker talks to the ls container over the network, No Licensing Service binaries are included.
# Stage 1: Install FRE and compile the CLI sample
FROM gcc:8 AS builder

ARG license_file
ARG license_password
ARG service_address

COPY ${license_file} /tmp/${license_file}
COPY FRE*.sh /tmp/FRE12.sh

RUN chmod +x /tmp/FRE12.sh && /tmp/FRE12.sh -- \
    --install-dir "/opt/ABBYY/FREngine12" \
    --license-path "/tmp/${license_file}" \
    --license-password "${license_password}" \
    --service-address "${service_address}" \
    --developer-install

WORKDIR /opt/ABBYY/FREngine12/Samples/CommandLineInterface
RUN make

# Remove developer-only library (not needed at runtime)
RUN rm /opt/ABBYY/FREngine12/Bin/libProtection.Developer.so

# Stage 2: Minimal runtime image
FROM ubuntu:noble

RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
    apt-get install --no-install-recommends -y \
    ca-certificates bash libc6 libglib2.0-0 libgcc-s1 libstdc++6 \
    zlib1g libx11-6 libfreetype6 libxext-dev libice-dev libsm-dev \
    locales && \
    locale-gen en_US.UTF-8 && \
    rm -rf /var/lib/apt/lists/*

# Copy FRE runtime binaries and data
COPY --from=builder /opt/ABBYY/FREngine12/Bin /opt/ABBYY/FREngine12/Bin
COPY --from=builder /opt/ABBYY/FREngine12/Data /opt/ABBYY/FREngine12/Data

# Copy license file (works for both .ActivationToken and .LocalLicense)
COPY --from=builder /var/lib/ABBYY/SDK/12/Licenses/*.ABBYY.* /var/lib/ABBYY/SDK/12/Licenses/

# Copy compiled CLI sample and demo image
COPY --from=builder /opt/ABBYY/FREngine12/Samples/CommandLineInterface/CommandLineInterface /app/
COPY --from=builder /opt/ABBYY/FREngine12/Samples/SampleImages/Demo.tif /app/

ENV LD_LIBRARY_PATH=/opt/ABBYY/FREngine12/Bin
ENV LANG=en_US.UTF-8
ENV LC_ALL=en_US.UTF-8

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh

The worker’s entrypoint is simpler than the single-container version because it does not manage the Licensing Service. The worker simply runs the sample and prints the output.
#!/bin/bash

# Run the CLI sample with the provided arguments
/app/CommandLineInterface $1

status=$?
if [ $status -ne 0 ]; then
  echo "Failed to launch app: $status"
  exit $status
fi

# Display the output file contents
cat ${1##*-of}
echo "Done"

Customizing the CLI Sample

Both setup options run the same default command in docker-compose.yml:
command: ["-if /app/Demo.tif -f TextUnicodeDefaults -of /app/Test.txt"]
  • -if — input file
  • -f — output format profile
  • -of — output file
Edit this line to point at a different input, output, or format profile. See the FRE Code Samples Library documentation for the full list of CLI arguments.
To run OCR on your own files, bind-mount a host directory into /app and point -if/-of at files inside it.

Common Issues

The following are known issues that apply to both setup options:
  • shm_size: 1g is mandatory. FRE relies on POSIX shared memory and the default 64MB /dev/shm allocation is not enough. The compose files above already set this on the worker service.
  • The installer and license file must be in the build context. Both Dockerfiles COPY FRE*.sh and the license file — if they are not in the directory you are building from, the build fails immediately. Do not mount the license at runtime. It is activated during the build.
  • Online licenses need network egress from the builder and the runtime. The builder needs it to activate; the runtime Licensing Service needs it to keep validating.
  • Do not commit license files or installers. In source control, add .env, *.ABBYY.*, and FRE*.sh to your ignore list, and do not include them in any published images unless you understand the implications and risks.
  • These examples use ubuntu:noble (24.04 LTS). Previous documentation referred to Ubuntu bionic, which is end-of-life. Package names differ between Ubuntu releases. For example: libgcc-8-dev is now libgcc-s1 and libstdc++-8-dev is now libstdc++6. If you use a different base image, verify the package list accordingly.

See also

Installing the Licensing Service on Linux Licensing Activation