---
title: "Deploy the TinyMCE Image Proxy server-side service using Docker"
description: "Deploy the TinyMCE Image Proxy server-side service using Docker."
canonical_url: "https://www.tiny.cloud/docs/tinymce/latest/individual-image-proxy-container/"
md_url: "https://www.tiny.cloud/docs/tinymce/latest/individual-image-proxy-container/index.md"
version: "latest"
last_updated: "2026-06-30T05:19:48Z"
tokens: 3641
---
# Deploy the TinyMCE Image Proxy server-side service using Docker

## Overview

The Image Proxy service is a server-side component that fetches and serves image content for the TinyMCE editor. It runs on-premises within the host infrastructure and provides the back-end capabilities used by the [Image Editing](/docs/tinymce/latest/editimage/) plugin. The service only retrieves image content; image editing is performed in the browser, and the service does not resolve media embeds.

The only requirement to run the Image Proxy service on-premises is a container runtime or orchestration tool, such as Docker, Kubernetes, or Podman.

A valid access token is required to access the Tiny Cloud Docker registry and pull the Docker image. Contact [Tiny Support](/contact/) to request the access token.

> **Warning:** Pushing this Docker image to a public container registry violates the Tiny Self-Hosted Software License Agreement, *including*:
> 
> - [The Tiny Self-Hosted Software License Agreement - (Enterprise Users)](/legal/tiny-self-hosted-enterprise-agreement/).
> - [The Tiny Self-Hosted Software License Agreement - (OEM & SaaS Users)](/legal/tiny-self-hosted-oem-saas-agreement/).

## Requirements

- The [Docker Engine](https://docs.docker.com/engine/docker-overview/) is installed and running.
- The user has Administrative or Root user access to run the Docker commands.
- The user is either:

  - Using a Unix-like operating system, such as Linux or macOS.
  - Using Windows and has access to unix command line tools using [Git for Windows](https://gitforwindows.org/), [Cygwin](https://www.cygwin.com/), or the [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10).

## Installation

> **Important:** A valid access token is **required** in order to retrieve On-Premises services images from Tiny Cloud Docker Registry. [Contact Tiny Support](/contact/) to request the access token.

### Retrieve Docker Image

1. Login into the Tiny Cloud Docker Registry:

```sh
docker login -u tiny -p [access-token] registry.containers.tiny.cloud
```
2. Pull the Docker Image from the Docker registry:

```sh
docker pull registry.containers.tiny.cloud/image-proxy-tiny:<VERSION>
```
Replace `<VERSION>` with `latest` or the specific version number.

> **Note:** Currently, the Docker images are only supported on x86-64 (also known as AMD64) architecture processors.
> === Specify Configurations
After completing the previous steps, run the Docker container from the pulled image:

```sh
docker run -p 19040:19040 registry.containers.tiny.cloud/image-proxy-tiny:<VERSION>
```
This triggers `-p 19040:19040`, exposing the service on `localhost:19040`. The service runs on port `19040` inside the Docker container, and this maps it to the same port on your localhost.

If set up correctly, the logs should display output similar to the following:

```log
2025-09-22 00:04:26 [io-compute-8] INFO  emissary - emissary
...
2025-09-22 00:04:26 [io-compute-blocker-8] INFO  emissary - -> Raw Config assembled from various sources: ConfigOrigin(merge of /app/application.conf: 1,system properties,reference.conf @ jar:file:/app/emissary.jar!/reference.conf: 1)
2025-09-22 00:04:26 [io-compute-blocker-8] WARN  c.e.d.config.AllowedOriginsConfig$ - No allowed-origins specified in config!
2025-09-22 00:04:26 [io-compute-blocker-8] INFO  emissary - emissary config loaded successfully: EmissaryConfig(SdkHttpConfig(HttpConfig(100,10,10,3,HttpConfigTimeouts(10,10,10),JvmTrustModel()),None),OriginWhitelist(List(),OriginPrecision(true)),Some(10000000))
2025-09-22 00:04:27 [io-compute-7] INFO  o.h.b.c.nio1.NIO1SocketServerGroup - Service bound to address /[0:0:0:0:0:0:0:0]:19040
2025-09-22 00:04:27 [io-compute-7] INFO  o.h.blaze.server.BlazeServerBuilder -
  _   _   _        _ _
 | |_| |_| |_ _ __| | | ___
 | ' \  _|  _| '_ \_  _(_-<
 |_||_\__|\__| .__/ |_|/__/
             |_|
2025-09-22 00:04:27 [io-compute-7] INFO  o.h.blaze.server.BlazeServerBuilder - http4s v0.23.27 on blaze v0.23.16 started at http://[::]:19040/
```
Running this command will generate a log warning about `allowed-origins` not being configured. This is expected, as it will be set up in the next step.

The TinyMCE server-side components require a configuration file to function correctly. By convention, this file is named `application.conf`. For more information, refer to [Required configuration for the server-side components](/docs/tinymce/latest/configure-required-services/).

This configuration file requires at least the following information:

- allowed-origins - Specifies the domains allowed to communicate with server-side editor features. This is **mandatory** for all server-side components.

The following settings for the premium server-side components are optional and will apply to all services that make outgoing HTTP/HTTPS requests using the configuration file.

- [proxy configuration](/docs/tinymce/latest/configure-common-settings-services/#proxy)
- [http configuration](/docs/tinymce/latest/configure-common-settings-services/#http)

The following settings for the Image Proxy service premium server-side component are optional:

- [image-proxy configuration](/docs/tinymce/latest/configure-imageproxy-service/#image-proxy)

### Run the Docker Container

The Docker container can also be run with `docker compose`. In this example, the following directory structure is assumed:

```sh
tiny-image-proxy/
└── docker-compose.yaml     # Docker Compose file to define and run the service
└── application.conf        # Configuration file for allowed origins and other settings
```
Here is an example of the `application.conf` file with the basic configurations:

```conf
ephox {
  allowed-origins {
    origins = [
      "http://example.com",
      "http://good.com",
      "*.my.company.org"
    ]
  }
}
```
Once the application configuration file is ready, proceed with the Docker Compose setup to configure and run the service.

1. Create the `docker-compose.yaml` file:

```yaml
services:
  image-proxy-tiny:
    image: registry.containers.tiny.cloud/image-proxy-tiny:[version]
    ports:
      - "19040:19040"
    restart: always
    init: true
    volumes:
      - type: bind
        source: ./application.conf #change this to the path on your local machine
        # Use the below target path if using any version below 2.111.12.
        # target: /ephox-image-proxy/ephox-image-proxy-docker-env.conf
        target: /app/application.conf
        read_only: true
```

> **Note:** From version 2.111.12 onwards, the `target` path in the volumes option must point to `/app/application.conf`.
2. Run the service (within the same directory where `docker-compose.yaml` was placed):

```sh
docker compose up
```
If the setup is correct, the initiation logs should appear as follows:

```log
✔ Container image-proxy-tiny-image-proxy-tiny-1                                                                                                                         Created0.2s
Attaching to image-proxy-tiny-1
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-9] INFO  emissary - emissary
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-9] INFO  emissary - * External Configuration
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-9] INFO  emissary -   * External configuration via System Properties
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -     * parseConfigSources
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -       * looking up property: ephox.config.url
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -         -> Property not set
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -       * looking up property: config.url
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -         -> Property not set
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -     * parseConfigSources
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -       * looking up property: ephox.config.file
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -         -> Found value for property: /app/application.conf
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -       * Parsing config defined by /app/application.conf from property: ephox.config.file
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -         -> Processing file: /app/application.conf
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -   * External application.conf => /opt/ephox/application.conf
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -     * Optional File (/opt/ephox/application.conf). Defaults to empty if file not found
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary - * Internal Configuration
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -   -> No extra internal configuration specified - skipping
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary - * Default (Reference) Configuration
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary -   * Loading configuration files from classpath (reference.conf and integration.conf). Neither is required.
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary - -> Raw Config assembled from various sources: ConfigOrigin(merge of /app/application.conf: 1,system properties,reference.conf @ jar:file:/app/emissary.jar!/reference.conf: 1)
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  c.e.d.config.AllowedOriginsConfig$ - Read allowed-origins config (ignoring ports = true) as:
image-proxy-tiny-1  |  - localhost:8000
image-proxy-tiny-1  |  - example.com
image-proxy-tiny-1  |  - good.com
image-proxy-tiny-1  |  - my.company.org
image-proxy-tiny-1  | 2025-09-22 00:14:39 [io-compute-blocker-9] INFO  emissary - emissary config loaded successfully: EmissaryConfig(SdkHttpConfig(HttpConfig(100,10,10,3,HttpConfigTimeouts(10,10,10),JvmTrustModel()),None),OriginWhitelist(List(localhost:8000, example.com, good.com, my.company.org),OriginPrecision(true)),Some(10000000))
image-proxy-tiny-1  | 2025-09-22 00:14:40 [io-compute-2] INFO  o.h.b.c.nio1.NIO1SocketServerGroup - Service bound to address /[0:0:0:0:0:0:0:0]:19040
image-proxy-tiny-1  | 2025-09-22 00:14:40 [io-compute-2] INFO  o.h.blaze.server.BlazeServerBuilder -
image-proxy-tiny-1  |   _   _   _        _ _
image-proxy-tiny-1  |  | |_| |_| |_ _ __| | | ___
image-proxy-tiny-1  |  | ' \  _|  _| '_ \_  _(_-<
image-proxy-tiny-1  |  |_||_\__|\__| .__/ |_|/__/
image-proxy-tiny-1  |              |_|
image-proxy-tiny-1  | 2025-09-22 00:14:40 [io-compute-2] INFO  o.h.blaze.server.BlazeServerBuilder - http4s v0.23.27 on blaze v0.23.16 started at http://[::]:19040/
```

### Next Steps

1. Test the service via cURL command

To verify that the Image Proxy service is set up and functioning correctly within the container, ensure the service is running on port `19040`. Once active, it should be ready to receive requests. The expected outputs below confirm proper configuration, assuming `http://good.com` is in the allowed origins and `http://bad.com` is not.

To check the service is running use:

```sh
curl http://localhost:19040/version
```
An example output is: `2.111.1`

To confirm that a request is being sent to the Image Proxy service, use:

```sh
curl --location 'http://localhost:19040/2/image?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsrikomm%2FBMP-EDITING%2Frefs%2Fheads%2Fmaster%2Fsrc%2FInputs%2Ffish.bmp' \
--header 'Origin: http://good.com'
```
Finally, to verify if a request is unauthorized and originates from an incorrect origin, use:

```sh
curl --location 'http://localhost:19040/2/image?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsrikomm%2FBMP-EDITING%2Frefs%2Fheads%2Fmaster%2Fsrc%2FInputs%2Ffish.bmp' \
--header 'Origin: http://bad.com'
```
If an error occurs, the expected message is: `{ "message": "The supplied authentication is not authorized to access this resource" }`.
2. Test directly in TinyMCE

Before deploying, it is recommended to test this service within the TinyMCE editor itself.

To do this, configure the [Image Editing](../editimage/) feature in the editor and call it via `tinymce.init`. If running locally on the default port `19040`, use the following settings:

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  toolbar: 'image',
  plugins: 'image editimage',
  editimage_cors_hosts: [ 'example.com', 'good.com' ],
  editimage_proxy_service_url: "http://localhost:19040"
});
```
