Engineering in Program Management — Run Jira Server in Docker

In large organizations, the deployment of incredible software solutions can often be immediately constrained by overly strict roles and permissions. Their full potential, closely guarded by layers of administrative rules, can never be realized.

# Problem

Embarking on the esteemed mission to recommend process improvements across numerous engineering teams, we sometimes find ourselves navigating through a dense fog of uncertainty and legally-required red tape, which can slow our progress to a crawl or even bring us to a complete standstill.

Together, we've stepped into a pivotal role within a committee that's spearheading the latest project-management revolution: transitioning to Jira from another software development planning solution. Our collective task is to design the project architecture, workflows, and integrations spanning various domains including business, design, product development, engineering, quality assurance, release management, operations, and support.

But with all of the red tape and permissions lockdowns, how can we truly test the limits of what is possible? It hit me — can Jira Server be installed on a local machine?

My engineering brain kicked in. This must be possible. It will allow a non-destructive, permissions-free playground to explore the possibilities!

# Solution ❤️

Let's run Jira Software Server in Docker! We can do anything we want without waiting for approvals and permissions grants. In fact, we can set our own permissions, user roles, project configuration, workflow structure, and anything else we've grown to love and hate about Jira.

Let us set sail and mark our course for Jira island!

# tl;dr

Have a GitHub repository with some make utils and needed files. Follow the README for a map of that route.

# Running Jira Server in Docker

Atlassian, the company behind Jira, provides download sources and trial licenses for their various products. We can easily stand up our own instance in Docker, with minimal effort.

Warning

Data persistence is questionable in demo mode (and Docker) — hope for the best and plan for the worst. Expect to lose the entire installation, settings, projects, workflows, etc. often. We'll cover seeding data in a future post.

Atlassian provides a Docker image and some guidance to get up and running on ARM64 architecture, but there are simpler, faster courses towards the land ahead.

Thanks to a short and sweet article by Alexey Matveev, we can unlock the secrets of unmanaged Jira bliss in about 20 minutes.

# Steps

# 1. Dockerfile

We'll start by creating a Dockerfile, incorporating the necessary commands to build our Jira environment. This file lays the foundation for our Docker-based Jira setup.

Dockerfile
FROM ubuntu:latest
WORKDIR /home
RUN apt update
RUN apt --assume-yes install openjdk-11-jdk curl
RUN mkdir -p downloads
RUN cd downloads
RUN mkdir -p jirahome
RUN curl https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-9.13.1.tar.gz --output atlassian-jira-software-9.13.1.tar.gz
RUN tar -xvf atlassian-jira-software-9.13.1.tar.gz
ENV JIRA_HOME=/home/downloads/jirahome
CMD ["atlassian-jira-software-9.13.1-standalone/bin/start-jira.sh", "-fg"]

Let's put this into a Dockerfile somewhere on our system. Navigate there and create the file. Then...

# 2. Build the Image

docker build -t jira-software-arm64:9.13.1 .

❯ docker build -t jira-software-arm64:9.13.1 .
[+] Building 1.1s (13/13) FINISHED

Note that one can change the target name to match underlying architecture. I have an M1 processor, thus the image name is jira-software-arm64 upon build completion.

Docker desktop, displaying our build Jira Server image, tagged as "9.13.1".

# 3. docker-compose.yml

We proceed by crafting a docker-compose.yml file, placing it alongside our Dockerfile. This file orchestrates the Docker environment, setting up Jira and a supporting PostgreSQL database service.

docker-compose.yml
1
version: "3"
2

3
services:
4
  jira:
5
    depends_on:
6
      - postgresql
7
    image: jira-software-arm64:9.13.1
8
    networks:
9
      - jiranet
10
    volumes:
11
      - jiradata:/var/atlassian/jira
12
    ports:
13
      - "8080:8080"
14
    logging:
15
      # limit logs retained on host to 25MB
16
      driver: "json-file"
17
      options:
18
        max-size: "500k"
19
        max-file: "50"
20

21
  postgresql:
22
    image: postgres:9.5-alpine
23
    networks:
24
      - jiranet
25
    volumes:
26
      - postgresqldata:/var/lib/postgresql/data
27
    environment:
28
      # Database hostname is `postgresql` inside Jira
29
      - "POSTGRES_USER=jira"
30
      # CHANGE THE PASSWORD!
31
      - "POSTGRES_PASSWORD=Postgres_password"
32
      - "POSTGRES_DB=jiradb"
33
      - "POSTGRES_ENCODING=UNICODE"
34
      - "POSTGRES_COLLATE=C"
35
      - "POSTGRES_COLLATE_TYPE=C"
36
    logging:
37
      # limit logs retained on host to 25MB
38
      driver: "json-file"
39
      options:
40
        max-size: "500k"
41
        max-file: "50"
42

43
volumes:
44
  jiradata:
45
    external: false
46
  postgresqldata:
47
    external: false
48

49
networks:
50
  jiranet:
51
    driver: bridge

Be sure to change the image name under services: -> jira: -> image: up there on line 7 to fit our image's name from the previous docker build command.

Now run docker-compose up and, after some time, behold Jira running on http://localhost:8080:

jira-1        |                   `sMMMMMMMMMMMMMM+
jira-1        |                      MMMMMMMMMMMMMM
jira-1        |                      :sdMMMMMMMMMMM
jira-1        |                              MMMMMM
jira-1        |           `sMMMMMMMMMMMMMM+  MMMMMM
jira-1        |              MMMMMMMMMMMMMM  +MMMMM
jira-1        |               :sMMMMMMMMMMM   MMMMM
jira-1        |                      MMMMMM    `UOJ
jira-1        |    `sMMMMMMMMMMMMM+  MMMMMM
jira-1        |      MMMMMMMMMMMMMM  +MMMMM
jira-1        |       :sdMMMMMMMMMM   MMMMM
jira-1        |              MMMMMM    `UOJ
jira-1        |              MMMMMM
jira-1        |              +MMMMM
jira-1        |               MMMMM
jira-1        |                `UOJ
jira-1        |
jira-1        |       Atlassian Jira
jira-1        |       Version : 9.13.1

# Configuration

Initial setup of our new Jira Software Server instance requires some configuration. This process involves connecting to the internal postgresql service, configuring database settings, and, finally, licensing. At the first screen, we're presented with setup options:

The Jira setup welcome page, which provides options to auto-configure with Atlassian's help, or manually set up.

We can configure this instance to run with the internal postgresql service, which can be used for database exploration and maintenance. Select the second, "I'll set it up myself" option.

Settings are included in the docker-compose.yml file previously illustrated. Be sure to select the radio-button option "My Own Database (recommended for production environments)", and fill in:

The Database setup page, where we'll configure the settings for database type, hostname, port number of the database service, database name, user name, password, and schema.

Click that "Test Connection" button, to confirm the database is configured correctly. The message we've been waiting all our lives to see will present itself:

The database configuration page, updated with the text "The database test was successful".

Click "Next" — this is definitely going to take at least a minute.

The database configuration page confirming setup has begun. It reads "Please wait while the database is set up. This may take a minute..."

Upon successful installation, we have the option to turn on "Private" or "Public" mode. Depending on our needs, we may wish to make the instance public, so it's easy to mock data and user interactions.

For our use-case, we might want it semi-locked down, to mimic real-world settings and constraints in a rules-and regulations environment.

The application properties page, where we configure if this Jira instance is public or private, the overall title for our Jira instance (application name), and its base URL.

Let's click "Next". We will then be prompted for a license key.

The "Specify license key" section, where we'll enter the generated license key from Atlassian.

Now we can generate one within our MyAtlassian account.

The MyAtlassian licenses page, where one can generate an evaluation license.

We want a license for "Jira Software (Data Center)":

The Atlassian "new trial license" page, where we've selected "Jira Software (Data Center)", as opposed to "Jira Software (Cloud)".

From here, we will provide an Organization name, the status of our Jira instance, which is "up and running", and the Server ID, which is back in localhost.

The Jira license setup page, which provides an option to "Generate a License"

Click that "Generate License" button and plate up some copypasta back in localhost:

The "Specify your license key" page, with license filled in.

Click next, and wait for license configuration to complete. We're then presented with the admin account set up screen:

The administrator account page, where we set Full name, email address, username, and password for the main admin account.

The rest is pretty straightforward. Answer some obvious questions, set a password, configure email notifications? Wait... Pick a language, avatar, then:

An option to "See a project in action - Create and explore a project that's pre-loaded with sample data."

To get some placeholder data set up, go with this option. Pick a flavor of project, and you'll end up with (Kanban):

A sample Jira project board, with various Issues in different states.

# Conclusion

I hope this quick write up helps someone who is curious what may be possible with process management in a business setting where things may be locked down.

In the future, I'll be expanding on this series. In fact, everything here is included in a jira-tools repository, along with a Makefile to simplify commands.

By adjusting the system architecture settings to match our host machine, we unlock new levels of capability and flexibility. Together, we're not just navigating the complexities of software management; we're mastering them.

Drop anchor sailors—land ho!

Back to Top