> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Running FRE 12 inside Docker containers on Linux

This topic describes how to run ABBYY FineReader Engine 12 inside Docker containers on Linux.

There are two setup options covered in this topic:

| Option                                                     | Description                                                                                                                                                                                                   |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**Single container**](#setup-option-1-—-single-container) | Licensing Service and FRE worker packaged together. <br /><br />Simpler; good for testing, demos, and single-shot OCR jobs.                                                                                   |
| [**Two containers**](#setup-option-2-—-two-containers)     | Licensing Service and FRE worker in separate containers. <br /><br />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

<Accordion title="Online license details">
  * 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.
</Accordion>

### Local license

<Accordion title="Local license details">
  * 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.
</Accordion>

## 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

<Accordion title="Single container details">
  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:

     ```bash theme={null}
     docker compose up
     ```

  The CLI sample will processes the bundled `Demo.tif` using OCR and prints the recognized text to the console.

  ### `.env`

  ```env theme={null}
  # 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`

  ```yaml theme={null}
  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"]
  ```

  <Warning> `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.</Warning>

  ### `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.

  ```dockerfile theme={null}
  # 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`

  ```bash theme={null}
  #!/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
  ```
</Accordion>

***

## Setup option 2 — Two containers

<Accordion title="Two container details">
  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.

  <Warning> 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. </Warning>

  ### 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:

     ```bash theme={null}
     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`

  ```yaml theme={null}
  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).

  ```dockerfile theme={null}
  # 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.

  ```dockerfile theme={null}
  # 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.

  ```bash theme={null}
  #!/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"
  ```
</Accordion>

***

## Customizing the CLI Sample

Both setup options run the same default command in `docker-compose.yml`:

```yaml theme={null}
command: ["-if /app/Demo.tif -f TextUnicodeDefaults -of /app/Test.txt"]
```

* `-if` — input file
* `-f` — output format profile
* `-of` — output file

<Note>
  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.
</Note>

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](/fine-reader/engine/distribution/distribution-linux/activating-the-library-linux/installing-the-licensing-service-on-linux)

[Licensing](/fine-reader/engine/licensing)

[Activation](/fine-reader/engine/licensing/activation)
