Article
· 7 hr ago 22m read

Running InterSystems IRIS with Docker: A Step-by-Step Guide - Part 1: From the Basics to Custom Dockerfile

Table of Contents

  1. Purpose of the article
  2. What containers are and why they make sense with IRIS
     2.1 Containers and images in a nutshell
     2.2 Why containers are useful for developers
     2.3 Why IRIS works well with Docker
  3. Prerequisites
  4. Installing the InterSystems IRIS image
     4.1 Using Docker Hub
     4.2 Pulling the image
  5. Running the InterSystems IRIS image
     5.1 Starting an IRIS container
     5.2 Checking container status
     5.3 Executing code in the container terminal
     5.4 Accessing the IRIS Management Portal
     5.5 Connecting the container to VS Code
     5.6 Stopping or removing the container
     5.7 Setting a specific password with a bind mount
     5.8 Using durable %SYS volumes
      5.8.1 What gets stored with durable %SYS
      5.8.2 How to enable durable %SYS
  6. Using Docker Compose
     6.1 Docker Compose example
     6.2 Running Docker Compose
  7. Using a Dockerfile to run custom source code
     7.1 Dockerfile example
     7.2 Docker Compose example
     7.3 Understanding layers, image tagging and build vs. run time
     7.4 Source code and init script
     7.5 Building the image with Dockerfile
     7.6 Running instructions in the containerized IRIS terminal
  8. Conclusion and what’s next


1. Purpose of the article

The InterSystems Developer Community already has plenty of great articles explaining what Docker is, the most important commands, and several use cases for InterSystems IRIS in a containerized environment.

The purpose of this series of articles is a bit different. Since I am a big fan of step-by-step guides, I want to create a comprehensive walkthrough on how to configure and use Docker with InterSystems IRIS, starting with the very basic and gradually move towards more advanced scenarios like multi-namespace instances, interconnected containers, integrations with external systems, and application comprehending an UI.

2. What containers are and why they make sense with IRIS

2.1 Containers and images in a nutshell

Traditionally, running an application required matching the version to your operating system and packaging it for that specific target. At the same time, every application should be packaged to specifically work with a target system. If you wanted an application to run on macOS and Windows, you had to change the application design and package it for the different systems. Docker images and containers are application deployment technologies that solve this problems by letting developers package software once and run it anywhere. 

Docker is a software platform that packages software into containers. A Docker image, or container image, is a standalone, executable file containing all the instructions (libraries, dependencies, and files) to create and run a container. A Docker image is shareable and portable, so you can deploy the same image in multiple locations at once. A Docker container is a runtime environment with all the necessary components needed to run the application code without using host machine dependencies.  

Unlike virtual machines, containers are lightweight. They don’t need a full operating system and runs directly on the host operating system through the Docker Engine using only the binaries and libraries required for the specific application, which makes it more efficient. Multiple isolated containers can be started in parallel on the same machine without interfering with each other.

2.2 Why containers are useful for developers

  • Isolation: run in a clean, reproducible environment without affecting your host system.
  • Reproducibility: ensure your setup works the same way across different machines.
  • Easy setup: launch an IRIS instance in seconds with a single command, without a manual installation.

2.3 Why IRIS works well with Docker

Running InterSystems IRIS in Docker has several advantages:

  • Application run and can be tested in isolated containers,
  • Enable using shared version control systems (such as Git) instead of working directly on server
  • Containerized environment can be replicated at any staging enabling consistency through all the software devilery lifecycle.
  • Your application can easily run on every computer.

3. Prerequisites

To run InterSystems IRIS in a Docker container you must have:

4. Installing InterSystems IRIS image

4.1 Using Docker Hub

Docker Hub is the central registry for Docker images. It provides a vast library of pre-built images you can use as a starting point. InterSystems publishes the official IRIS Community Edition images there, which you can download to run IRIS locally in your container. You can also use Docker Hub to push your own custom images for sharing within your team or distributing to the community. Docker Hub is both available online an embedded into Docker Desktop.

4.2 Pulling the Image

Some common Docker image commands are:

Command Description
docker pull <image> Download an image from Docker Hub
docker images List all local images
docker rmi <image> Remove one or more images

You can find the exact pull command directly on the Docker Hub page of the image:

For the InterSystems IRIS image the command is:

docker pull intersystems/iris-community:latest-cd

Alternatively, you can search for iris-community inside Docker Desktop search bar and click Pull:

Once installed, you should have the InterSystems IRIS image listed among your local images:

5. Running the InterSystems IRIS Image

Once the InterSystems IRIS image has been pulled from Docker Hub, you can run it inside a container. 

The following are common commands for Docker containers:

Command Description
docker run -d <image> Run in detached mode: starts the container in the background and return control to the terminal immediately.
docker run -p <host>:<container> <img> Map host port to container port
docker ps List running containers
docker ps -a List all containers (including stopped)
docker exec -it <container> bash Execute a command inside a running container
docker logs <container> View logs of a container
docker stop <container> Stop a running container
docker start <container> Start a stopped container
docker restart <container> Restart a container
docker rm <container> Remove a container

5.1 Starting an IRIS Container

You can start an InterSystems IRIS Community Edition container named "my-iris" through the Docker Desktop UI simply by clicking the Run button of the image you want to run in the Images panel. For the InterSystems image it is possible to specify a few optional settings, like which ports to expose on your host machine to communicate with the services running inside the container.

This could be done through the menu shown above, considering that:

  • left side → port on the host machine
  • right side → port inside the container

Common IRIS Ports (inside the container)

  • 1972 → Superserver Port: used by IRIS for network protocols (ObjectScript, JDBC, etc.).
  • 52773 → Web Server Port: used by IRIS for the Management Portal (web interface).

If you do not explicitly map the ports, Docker will assign random ports on the host.

Alternatively, you can run the container using the terminal:

docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 intersystems/iris-community:latest-cd

In this example:

  • 9091 on the host is mapped to 1972 inside the container (Superserver).
  • 9092 on the host is mapped to 52773 inside the container (Management Portal).

5.2 Checking container status

After running this command, run docker ps to verify if the container is running properly.

> docker ps
CONTAINER ID   IMAGE                                   COMMAND                 CREATED         STATUS                            PORTS                                                                                        NAMES
907d4c2b4ab5   intersystems/iris-community:latest-cd   "/tini -- /iris-main"   3 seconds ago   Up 2 seconds (health: starting)   0.0.0.0:9091->1972/tcp, [::]:9091->1972/tcp, 0.0.0.0:9092->52773/tcp, [::]:9092->52773/tcp   my-iris

Running containers are listed among Docker Desktop Containers panel as well:

The status of the related images will be "In Use", as shown in Images panel:

5.3 Execute code in the container terminal

Once the container status shows Running, everything is working correctly. 

You can test it by opening the container terminal (click on the container's name inside the Containers panel of Docker Desktop and go to Exec) and typing:

iris session IRIS

This opens an IRIS terminal inside the Docker container, where you can use standard ObjectScript syntax to execute commands and scripts.

5.4 Accessing the IRIS Management Portal of the containerized instance

Next, open your browser and navigate to:

http://localhost:9092/csp/sys/UtilHome.csp

By default, IRIS containers uses the _SYSTEM user with the password SYS. You are required to change the password after logging in.

This gives you full access to the IRIS Management Portalallowing you to manage namespaces, databases, and other IRIS features directly from the web interface.

5.5 Connecting the container to VSCode IDE

You can connect your preferred IDE (such as VS Code or Studio) to the IRIS container using the mapped Superserver port (default 1972 inside the container, e.g., 9091 on the host) and Web Server port (default 52773 inside the container, e.g., 9092 on the host). This allows you to develop and test ObjectScript code directly against the running container.

To connect the container to VSCode:

  • Install the InterSystems ObjectScript Extension Pack
  • Open the InterSystems Server extension
  • Click on three dots and "Edit server"
  •  
  • Click "Edit in settings.json"
  • Add this element to the "intersystems.servers" json:
"docker_iris": {
    "webServer": {
        "scheme": "http",
        "host": "localhost",
        "port": 9092
    },
    "description": "Connection to Docker container."
}
  • Now the server is connected. You can log in with _SYSTEM user.
  • As you can see, the USER namespace is the only available:

5.6 Stopping or removing the container

To stop a running container use the command:

docker stop my-iris

Start the container again

To start the container again use the command

docker start my-iris

Remove (delete) the container

To remove the container instance, but not the image use: 

docker rm my-iris

All data inside the container will be lost unless you’ve mounted volumes (we're talking about this in the next paragraphs).

5.7 Set a specific password using a bind mount

It is possible to set a custom password while starting a container by using a password file. The file will be saved on our host and copied into the container using the bind mount mechanism.

When you use a bind mount, a file or directory on the host machine is mounted from the host into a container, allowing to share source code or build artifacts between a development environment on the Docker host and a container. 

  • Create a file named password.txt containing just your password as a string (pay attention! Take a note with your password, you will need it later). 
  • Copy its path, in this example is C:\InterSystems\DockerTest\password\password.txt
  • Run the following command:
docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 --volume "C:\InterSystems\DockerTest:/durable" intersystems/iris-community:latest-cd --password-file /durable/password/password.txt 

Once the container is running you can log in with user _SYSTEM and the password you wrote in your password file. 

Inside docker container, you will see a password.txt.done file. The same file will be inside your host folder.

File extension is changed to .done to avoid the password from being left in plain text. This is the standard behavior in InterSystems IRIS with password files. Therefore, after the password is read from password.txt file and the default IRIS user (_SYSTEM) is updated with that password, the file is updated by appending .done and removing the password for security reasons.

You can log in to the Management Portal using your custom password (I told you to note it :D). InterSystems IRIS won't force you to change the password after you log in.

Please note that if the container is removed and then restarted without any mounted durable volume (for more information see the next paragraph), the password won't be read again from password.txt file, since it has been replaced by the password.txt.done. If that's the case, the standard "SYS" password will be used. 

5.8 Start container with a specific durable volume

By default, anything you save inside a running Docker container disappears when you remove it with the command docker rm <container's name> . 

To avoid losing your data, InterSystems IRIS provides the durable %SYS feature. This allows the instance to store all important files on your host machine, so they survive container and instance restarts.

5.8.1 What gets stored with durable %SYS?

Some examples include:

  • Configuration files (iris.cpf, httpd.conf)
  • Web Gateway configs and logs (/csp)
  • System databases (IRIS, USER, IRISSECURITY, IRISTEMP, etc.)
  • Journals, write image file (WIJ), and temporary files
  • Log files (messages.log, SystemMonitor.log, etc.)
  • License key (iris.key)
  • Any other databases you’ve created

5.8.2 How to enable durable %SYS

The first thing to do is picking a folder from your host, like C:\InterSystems\DockerTest

  • On Linux, make sure IRIS can write to it by creating the irisowner user and give him the ownership of the directory:
adduser irisowner
chown -R irisowner:irisowner /InterSystems/DockerTest
  • On Windows you can skip this passage because Docker Desktop will mount the folder with your current Windows user permissions.

Then, mount your host folder and tell IRIS where to write its durable data using the ISC_DATA_DIRECTORY variable:

  --volume "C:\InterSystems\DockerTest:/durable" --env ISC_DATA_DIRECTORY=/durable/iris

The complete instruction to run on the terminal is:

docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 --volume "C:\InterSystems\DockerTest:/durable" --env ISC_DATA_DIRECTORY=/durable/iris intersystems/iris-community:latest-cd --password-file /durable/password/password.txt

At this point, you can inspect your container and see that a durable folder is mounted and contains the directories iris/ (for the durable %SYS) and password/. On your host, you can see both the directories as well:

If the container is stopped and removed, when you recreate the container with the same Docker Compose command, IRIS will restore its previous state (users, config, logs, databases, etc.) using the data from the iris/ folder, so nothing is lost. You can test this by creating a web application, stopping and removing the container and creating it a second time. Without using the durable %SYS feature, any changes inside %SYS are lost when the container is removed and the instance is started as a new one each time. 

Please note that if you delete the iris/ folder, the next time you start the container IRIS it will be initialized like in a fresh installation because it won't find the previous %SYS data. A brand new iris/ folder will be created.

6. Using Docker Compose 

So far, you have been starting InterSystems IRIS with a single long docker run command. That works, but it quickly gets difficult to manage everything with plain shell commands.

Docker Compose is a YAML configuration file for defining how to run one or more containers. That simplifies the control of your entire application stack, making it easy to manage services, networks, and volumes. With a single command you can create and start all the services from your configuration file.

The following are common commands for Docker compose:

Command Description
docker compose up -d Start all services defined in docker-compose.yml in detached mode (by default, use the docker-compose.yml file in your current folder).
docker compose -f ./path/to/docker-compose.yml up -d Start services from a compose file in another directory.
docker compose down Stop and remove all containers, networks, and volumes created by docker compose up.
docker compose ps List the containers managed by Compose.
docker compose logs View logs from all services defined in the Compose file.
docker compose logs <service> View logs from a specific service (e.g., iris).
docker compose exec <service> bash Open a shell inside a running container managed by Compose.
docker compose stop Stop the running containers, but don’t remove them.
docker compose start Start the previously stopped containers.
docker compose restart Restart all containers defined in the Compose file.
docker compose build Build or rebuild the services defined by a Dockerfile.
docker compose pull Pull the latest image(s) for the services.
docker compose config Validate and view the merged configuration from the Compose file.

6.1 Docker Compose example

To use Docker Compose, you must create a docker-compose.yml file containing all the configurations for the container you want to create and start.

In this way the following command:

docker run --name my-iris -d --publish 9091:1972 --publish 9092:52773 --volume "C:\InterSystems\DockerTest:/durable" --env ISC_DATA_DIRECTORY=/durable/iris intersystems/iris-community:latest-cd --password-file /durable/password/password.txt

can be replaced by the docker-compose.yml below:

# docker-compose.yml     
services:
  iris:
    container_name: my-iris
    image: intersystems/iris-community:latest-cd
    init: true
    volumes:
      # System/persistent data (IRIS installation, databases, etc.)
      # On Windows, you can use either: "C:\\InterSystems\\DockerTest:/durable"
      - C:/InterSystems/DockerTest:/durable
    ports:
      - "9092:52773"  # Management Portal / REST APIs
      - "9091:1972"   # SuperServer port
    environment:
      - ISC_DATA_DIRECTORY=/durable/iris
    # Use the password file to log within the container
    command: --password-file /durable/password/password.txt

6.2 Running Docker Compose 

Open a terminal in the directory where the Docker Compose file is saved (or use the -f option) and run the following command:

docker compose up -d

Your IRIS container will start with the exact configuration specified in Docker Compose file.

In Docker Desktop, you can now see that a compose stack called "dockertest" (it takes the name of the folder in which the Docker Compose is saved) has been created and associated with the container "my-iris":

7. Using a Dockerfile to run custom source code

So far, you have been running InterSystems IRIS directly from the official Docker image. However, we may need to automatically load ObjectScript classes or other custom code within the image while building it. 

A Dockerfile is a text file with instructions for building an image, starting from a base image (like intersystems/iris-community:latest-cd). With a Dockerfile we can add custom source code into the container and run custom commands while building the image. 

7.1 Dockerfile example

The next example provides a Dockerfile that performs the following operations:

  • Start the image from the official InterSystems IRIS image.
  • Copy your application code from src/ folder into the container.
  • Run a script to import classes and initialize the containerized application and save the logs into a log file.
  • Expose the default InterSystems IRIS ports.

7.2 Docker Compose example

You should modify the Docker Compose as well, to specify to build the image from the Dockerfile in the current folder:

# docker-compose.yml     
services:
  iris:
    container_name: my-iris
    build: # this tells Docker to build a new image based on the one specified in the Dockerfile
      context: .        # build the image from local Dockerfile
      dockerfile: Dockerfile
    image: my-modified-iris-image:latest   # give the new image a new tag to avoid overriding the base image
    init: true
    volumes:
      # System/persistent data (IRIS installation, databases, etc.)
      # On Windows, you can use either: "C:\\InterSystems\\DockerTest:/durable"
      - C:/InterSystems/DockerTest:/durable
    ports:
      - "9092:52773"  # Management Portal / REST APIs
      - "9091:1972"   # SuperServer port
    environment:
      - ISC_DATA_DIRECTORY=/durable/iris
    # Use the password file to log within the container
    command: --password-file /durable/password/password.txt

7.3 Understanding layers, image tagging and build vs. run time

In Docker, as explained here: What is an image?, there are two important principles to keep in mind:

  1. Images are immutable: Once an image is created, it can't be modified. You can only make a new image or add changes on top of it.
  2. Container images are composed of layers: Each layer represents a set of file system changes that add, remove, or modify files.

New layers are added to an image when the instructions specified within a Dockerfile are executed. These layers will be shown in the image information as well.

With that in mind, it is really important to distinguish what Docker does at build time (when it creates an image from a Dockerfile) and at run time (when it starts a container from that image).

Each of these Dockerfile instruction are executed on build time

  • COPY: files are copied into the image
  • RUN: executes commands and saves the results as new image layers
  • ENTRYPOINT: doesn't change the filesystem but define the default process that will be launched at run time
  • EXPOSE: sets metadata about which ports the image intends to use

At run time, Docker doesn’t rebuild the image but adds a container layer on top of it. All changes made while the container is running (like new files, edits, logs) go into this temporary layer.

From the last provided Docker Compose example:

build: # this tells Docker to build a new image based on the one specified in the Dockerfile
  context: .        # build the image from local Dockerfile
  dockerfile: Dockerfile
image: my-modified-iris-image:latest   # give the new image a new tag to avoid overriding the base image

These instructions tell Docker to create a new image called "my-modified-iris-image:latest" (this is called tag) by pulling the base image and modifying it as described in the Dockerfile. Tagging the new image with a distinct name is really important. If we avoid putting a tag on the newly created image, the base image will be overridden by the new one. The official image will be still available on Docker Hub, but this local version will shadow it and every project referring to that tag will now unknowingly use the customized image, containing several new layers.

To avoid this, always use a distinct tag to create a new separate image while keeping the official base image clean and reusable. 

    7.4 Source code and init script

    At this point we should create at least one class and place it inside the src/ folder. The class will be copied into the container and imported through the iris.script file, which contains all the instructions to import the classes and initialize the application while building the image.

    Create a new directory called src/DockerStepByStep in your project folder and create the following class file:

    Class DockerStepByStep.cheers Extends %RegisteredObject
    {
    
    ClassMethod sayHi() As %Status
    {
        Set sc = $$$OK
        w "Hi mom!",!
        Return sc
    }
    
    }

    In the root of your project, create a file called iris.script:

    // Unexpire passwords for dev mode
    zn "%SYS"
    Do ##class(Security.Users).UnExpireUserPasswords("*")
    
    // Load classes from durable source
    zn "USER"
    // Import classes
    set importPath = "/opt/irisapp/src"
    write "Loading classes at '", importPath, "' ...", !
    set errors = ""
    do $System.OBJ.Import(importPath,"cuk",,.errors)
    if errors = 0 { write "Classes loaded successfully", ! } else { write errors, " errors occurred while loading classes!", ! }
    
    halt

    7.5 Build Image with Dockerfile

    For the first run you can use the following command to build the image from Dockerfile (the --build flag forces Docker to rebuild the image from your Dockerfile):

    docker-compose up --build

    For other runs, if Dockerfile has not been modified, you can simply run: 

    docker-compose up -d

    Once the image building is running, you will see this logs in the terminal:

    PS C:\InterSystems\DockerTest> docker-compose up --build
    [+] Building 21.5s (13/13) FINISHED
     => [internal] load local bake definitions                                                                     0.0s
     => => reading from stdin 530B                                                                                 0.0s
     => [internal] load build definition from Dockerfile                                                           0.0s
     => => transferring dockerfile: 1.73kB                                                                         0.0s
     => [internal] load metadata for docker.io/intersystems/iris-community:latest-cd                              10.0s
     => [internal] load .dockerignore                                                                              0.0s
     => => transferring context: 2B                                                                                0.0s 
     => [1/6] FROM docker.io/intersystems/iris-community:latest-cd@sha256:93488df381f5868649e7bfc33a9083a3e86a22d  0.9s 
     => => resolve docker.io/intersystems/iris-community:latest-cd@sha256:93488df381f5868649e7bfc33a9083a3e86a22d  0.0s 
     => [internal] load build context                                                                              0.0s 
     => => transferring context: 147B                                                                              0.0s
     => [2/6] WORKDIR /opt/irisapp                                                                                 0.0s
     => [3/6] COPY src src                                                                                         0.1s 
     => [4/6] COPY iris.script .                                                                                   0.1s
     => [5/6] RUN mkdir -p /opt/irisapp/logs                                                                       0.3s
     => [6/6] RUN iris start IRIS &&     iris session IRIS < iris.script > /opt/irisapp/logs/build.log 2>&1 &&     4.5s 
     => exporting to image                                                                                         4.5s 
     => => exporting layers                                                                                        3.3s 
     => => exporting manifest sha256:3ce316cefa21a3707251c4287005a15b02e6dc0151b24baf2a82f76064792250              0.0s 
     => => exporting config sha256:00238e19edef86b29149d2eb89ff75f4d1465ba0d9a2ac4494a14d3bd3746a94                0.0s 
     => => exporting attestation manifest sha256:3579cab5c8accc7958090276deb60bd7dbbc2ecbf13af8e7fa8c4ff2dfe91028  0.0s 
     => => exporting manifest list sha256:17b969c340f57d611cc7603287cc6db50cffd696258a72b5648ece0a919676ac         0.0s 
     => => naming to docker.io/intersystems/iris-community:latest-cd                                               0.0s 
     => => unpacking to docker.io/intersystems/iris-community:latest-cd                                            0.9s 
     => resolving provenance for metadata file                                                                     0.0s 
    [+] Running 3/3
     ✔ intersystems/iris-community:latest-cd  Built                                                                0.0s 
     ✔ Network dockertest_default             Created                                                              0.1s 
     ✔ Container my-iris                      Created                                                              0.2s 

    At step 6/6, the iris.script file is executed into the containerized IRIS instance and logs are saved at path /opt/irisapp/logs/build.log.

    To view logs you can run the instruction:

    docker exec -it my-iris cat /opt/irisapp/logs/build.log

    You should see the following records that inform you about the result of class compilation:

    Node: buildkitsandbox, Instance: IRIS
    
    USER>
    
    USER>
    
    %SYS>
    
    %SYS>
    
    %SYS>
    
    %SYS>
    
    USER>
    
    USER>
    
    USER>
    
    USER>
    Loading classes at '/opt/irisapp/src' ...
    
    USER>
    
    USER>
    
    Load of directory started on 09/16/2025 07:46:28
    Loading file /opt/irisapp/src/DockerStepByStep/cheers.cls as udl
    
    Compilation started on 09/16/2025 07:46:28 with qualifiers 'cuk'
    Class DockerStepByStep.cheers is up-to-date.
    Compilation finished successfully in 0.005s.
    
    Load finished successfully.
    
    USER>
    Classes loaded successfully
    
    USER>
    
    USER>

    On Docker Desktop, you can see that a new image calle "my-modified-iris-image" has been created and is running alongside the base official image.

    If you inspect the images, you will see that the custom one is composed of 31 layers, rather than the 25 layers of the original. The new layers correspond to the instructions executed at build time by the Dockerfile:

    7.6 Run instructions in containerized IRIS terminal

    To test the classes, you can activate the iris terminal within the containerized IRIS instance. To do so, execute the following instruction:

    docker exec -it my-iris iris session IRIS

    At this point you can invoke the ClassMethod from the USER namespace with the command:

    do ##class(DockerStepByStep.cheers).sayHi()

    Finally, you should see this output:

    PS C:\InterSystems\DockerTest> docker exec -it my-iris iris session IRIS
       
    Node: 41c3c7a9f2e4, Instance: IRIS
    
    USER>do ##class(DockerStepByStep.cheers).sayHi()
    Hi mom!

    8. Conclusion and what’s next

    We’ve walked through the full cycle of getting InterSystems IRIS running in Docker:

    • pulling the image
    • starting and configuring containers
    • persisting data with durable %SYS
    • building custom images with your own code and scripts

    This is enough to start experimenting with IRIS in a containerized environment and use it for development.

    A GitHub repo with all the files discussed in the final part (Docker Compose, Dockerfile, iris.script, etc..) is available.

    Stay tuned for the next article!

    Discussion (1)3
    Log in or sign up to continue