Table of Contents
- Purpose of the article
- 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 - Prerequisites
- Installing the InterSystems IRIS image
4.1 Using Docker Hub
4.2 Pulling the image - 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 - Using Docker Compose
6.1 Docker Compose example
6.2 Running Docker Compose - 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 - 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:
- Docker Engine installed and running:
- Install Docker Engine on Linux.
- Docker Engine is also available for Windows, macOS, and Linux, through Docker Desktop.
- Git to enable using shared source control repositories.
- Visual Studio Code to view and modify source code.
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 to1972
inside the container (Superserver).9092
on the host is mapped to52773
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 Portal, allowing 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:
- 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.
- 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 imageRUN
: executes commands and saves the results as new image layersENTRYPOINT
: doesn't change the filesystem but define the default process that will be launched at run timeEXPOSE
: 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!