master fafc3b843b6f cached
25 files
117.7 KB
34.6k tokens
1 requests
Download .txt
Repository: vromero/activemq-artemis-docker
Branch: master
Commit: fafc3b843b6f
Files: 25
Total size: 117.7 KB

Directory structure:
gitextract_c_rmc8jt/

├── .travis.yml
├── BUILD.md
├── LICENSE
├── Makefile
├── README.md
├── src/
│   ├── Dockerfile
│   ├── Dockerfile.alpine
│   └── assets/
│       ├── docker-entrypoint.sh
│       ├── enable-jmx.xml
│       ├── jmx-exporter-config.yaml
│       ├── merge.xslt
│       └── semver2.sh
├── tags.csv
└── test/
    ├── assets/
    │   ├── 1.x.x/
    │   │   └── etc-override/
    │   │       ├── broker-00.xml
    │   │       └── entrypoint-00.sh
    │   ├── 2.x.x/
    │   │   └── etc-override/
    │   │       ├── broker-00.xml
    │   │       └── entrypoint-00.sh
    │   ├── etc-override/
    │   │   └── jmx-exporter-config.yaml
    │   ├── goss.yaml
    │   ├── goss_wait.yaml
    │   ├── vars-etc-override.yaml
    │   └── vars.yaml
    ├── test-dockerfile.bats
    ├── test-entrypoint.bats
    └── test-image.bats

================================================
FILE CONTENTS
================================================

================================================
FILE: .travis.yml
================================================
language: bash
services: docker

env:
  - VERSION=1.0.0
  - VERSION=1.0.0 VARIANT=alpine
  - VERSION=1.1.0
  - VERSION=1.1.0 VARIANT=alpine
  - VERSION=1.2.0 
  - VERSION=1.2.0 VARIANT=alpine
  - VERSION=1.3.0 
  - VERSION=1.3.0 VARIANT=alpine
  - VERSION=1.4.0 
  - VERSION=1.4.0 VARIANT=alpine
  - VERSION=1.5.0
  - VERSION=1.5.0 VARIANT=alpine 
  - VERSION=1.5.1
  - VERSION=1.5.1 VARIANT=alpine
  - VERSION=1.5.2
  - VERSION=1.5.2 VARIANT=alpine
  - VERSION=1.5.3
  - VERSION=1.5.3 VARIANT=alpine
  - VERSION=1.5.4
  - VERSION=1.5.4 VARIANT=alpine
  - VERSION=1.5.5
  - VERSION=1.5.5 VARIANT=alpine
  - VERSION=1.5.6 
  - VERSION=1.5.6 VARIANT=alpine
  - VERSION=2.0.0 
  - VERSION=2.0.0 VARIANT=alpine
  - VERSION=2.1.0 
  - VERSION=2.1.0 VARIANT=alpine
  - VERSION=2.2.0 
  - VERSION=2.2.0 VARIANT=alpine
  - VERSION=2.3.0 
  - VERSION=2.3.0 VARIANT=alpine
  - VERSION=2.4.0 
  - VERSION=2.4.0 VARIANT=alpine
  - VERSION=2.5.0 
  - VERSION=2.5.0 VARIANT=alpine
  - VERSION=2.6.0
  - VERSION=2.6.0 VARIANT=alpine
  - VERSION=2.6.1
  - VERSION=2.6.1 VARIANT=alpine
  - VERSION=2.6.2
  - VERSION=2.6.2 VARIANT=alpine    
  - VERSION=2.6.3 
  - VERSION=2.6.3 VARIANT=alpine
  - VERSION=2.7.0 
  - VERSION=2.7.0 VARIANT=alpine
  - VERSION=2.8.0 
  - VERSION=2.8.0 VARIANT=alpine
  - VERSION=2.9.0 
  - VERSION=2.9.0 VARIANT=alpine
  - VERSION=2.10.0
  - VERSION=2.10.0 VARIANT=alpine
  - VERSION=2.10.1 
  - VERSION=2.10.1 VARIANT=alpine
  - VERSION=2.11.0 
  - VERSION=2.11.0 VARIANT=alpine
  - VERSION=2.12.0 
  - VERSION=2.12.0 VARIANT=alpine
  - VERSION=2.13.0 
  - VERSION=2.13.0 VARIANT=alpine
  - VERSION=2.14.0 
  - VERSION=2.14.0 VARIANT=alpine
  - VERSION=2.15.0
  - VERSION=2.15.0 VARIANT=alpine
  - VERSION=2.16.0
  - VERSION=2.16.0 VARIANT=alpine

before_install:
  - curl -L https://goss.rocks/install | sudo sh

install:
  - git clone https://github.com/vromero/activemq-artemis-docker.git ~/activemq-artemis-docker

before_script:
  - versionTag="${VERSION}${VARIANT:+-${VARIANT}}"
  - if [[ $TRAVIS_PULL_REQUEST == "false" ]] && [[ $TRAVIS_BRANCH == "master" ]]; then echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin; fi

script:
  - |
    (
      set -Eeuo pipefail
      set -x
      travis_retry make $versionTag 
      echo ---------------------------
      echo $TRAVIS_PULL_REQUEST
      echo $TRAVIS_BRANCH
      echo ---------------------------
      if [[ $TRAVIS_PULL_REQUEST == "false" ]] && [[ $TRAVIS_BRANCH == "master" ]]; then travis_retry make push_$versionTag; fi
    )



================================================
FILE: BUILD.md
================================================
# Building the ActiveMQ Artemis Docker Image

Depending on your platform the build process may differ slightly. Support for as many build platforms as possible is provided in a best effort basis.

If you consistently can reproduce a test failure, please search for it in the [issue tracker](https://github.com/vromero/activemq-artemis-docker/issues) or file a new issue.

## Prerequisites

To build the ActiveMQ Artemis Docker Image the following tools are necessary:

- Docker
- Make
- goss and dgoss
- shellcheck
- bats-core

## Supported Platforms

Only UN*X based operating systems are supported currently for building this image. 

## Building the image

To build all versions running all tests jus type

```bash
make
```

This will run the full build (with the exception of the deployment phase) for all versions presents in the filel `tags.csv`.

To just build *just one version* you can call `make` with `VERSION[-VARIANT]` where variant can be `-alpine` for an Alpine based image build or just nothing for a Debian based one, e.g:

```bash
make 2.6.0
```

```bash
make 2.6.0-alpine
```

It is also possible to just build the image without testing with `make build_2.8.0`, just testing: `make test_2.8.0`, running the image: `make run_2.8.0` or even run the image for a shell `make runsh_2.8.0`.

You can also override the artemis binary distribution url by passing a parameter containing a zip file containing the distribution.  ie.  `make BUILD_ARGS="--build-arg ACTIVEMQ_DISTRIBUTION_URL=https://repository.apache.org/content/repositories/releases/org/apache/activemq/apache-artemis/2.6.4/apache-artemis-2.8.0-bin.zip" 2.8.0`.   Note that you also need to pass in the version # as the first argument (ie 2.8.0)



================================================
FILE: LICENSE
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.



================================================
FILE: Makefile
================================================

.PHONY: help build test run all

VERSIONS_FILE=tags.csv

ALL_VERSION_TAGS=$(shell awk -F "," 'NR>1  {print $$2}' ${VERSIONS_FILE})
lookupFromTag=$(shell awk -F "," '$$2 == "$1" {print $$$2}' ${VERSIONS_FILE})
lookupRepositoryFromTag=$(call lookupFromTag,$1, 1)
lookupBaseImageFromTag=$(call lookupFromTag,$1, 3)
lookupÀliasesFromTag=$(call lookupFromTag,$1, 4)
lookupDockerfileFromTag=$(call lookupFromTag,$1, 5)

getPart=$(word $2,$(subst -, ,$1))
getVersionFromTag=$(call getPart,$1, 1)
getVariantFromTag=$(call getPart,$1, 2)
getFullTagNameFromTag=$(call lookupRepositoryFromTag,$1):$(call getVersionFromTag,$1)$(if $(call getVariantFromTag,$1),-$(call getVariantFromTag,$1),"")

%: build_% test_% tag_%
	

build_%:
	@cd src && \
	echo Building version $* && \
	docker build --quiet --build-arg ACTIVEMQ_ARTEMIS_VERSION=$(call getVersionFromTag,$*) --build-arg BASE_IMAGE=$(call lookupBaseImageFromTag,$*) $(BUILD_ARGS) -t $(call getFullTagNameFromTag,$*) -f $(call lookupDockerfileFromTag,$*) .

tag_%:
	@for alias in $(call lookupÀliasesFromTag,$*); do docker tag $(call getFullTagNameFromTag,$*) $$alias ; done

push_%:
	@docker push $(call getFullTagNameFromTag,$*)
	@for alias in $(call lookupÀliasesFromTag,$*); do docker push $$alias ; done

run_%: build
	docker run -i -t --rm $(call getFullTagNameFromTag,$*)

runsh_%: build
	docker run -i -t --rm $(call getFullTagNameFromTag,$*) /bin/sh

all: $(ALL_VERSION_TAGS)

test_%:
	@DOCKER_FILE=$(call lookupDockerfileFromTag,$*) COORDINATES=$(call getFullTagNameFromTag,$*) ACTIVEMQ_ARTEMIS_VERSION=$(call getVersionFromTag,$*) TAG=$* bats test/*.bats
	@echo

	


================================================
FILE: README.md
================================================
![latest 2.16.0](https://img.shields.io/badge/latest-2.16.0-blue.svg?style=flat) ![License MIT](https://img.shields.io/badge/license-APACHE-blue.svg) [![Build Status](https://travis-ci.org/vromero/activemq-artemis-docker.svg?branch=master)](https://travis-ci.org/vromero/activemq-artemis-docker) [![](https://img.shields.io/docker/stars/vromero/activemq-artemis.svg)](https://hub.docker.com/r/vromero/activemq-artemis 'DockerHub') [![](https://img.shields.io/docker/pulls/vromero/activemq-artemis.svg)](https://hub.docker.com/r/vromero/activemq-artemis 'DockerHub') [![Say Thanks!](https://img.shields.io/badge/Say%20Thanks-!-1EAEDB.svg)](https://saythanks.io/to/vromero)

## THIS PROJECT IS ARCHIVED 

It has been quite a ride but after a few years, with multiple initiatives going on around Artemis and Docker both from Redhat and from Apache, I've decided that its time to let these project take the spot the community around this project and I have been occuping till now.

Of course the project will remain read-only and you should feel free to fork but I won't be maintaining anymore.

## 1. What is ActiveMQ Artemis?

[Apache ActiveMQ Artemis](https://activemq.apache.org/artemis) is an open source project to build a multi-protocol, embeddable, very high performance, clustered, asynchronous messaging system. Apache ActiveMQ Artemis is an example of Message Oriented Middleware (MoM).

![logo](https://activemq.apache.org/assets/img/activemq_logo_black_small.png)

## 2. Tags and `Dockerfile` links

| Debian Based                                                                                 | Alpine Based                                                                                               |
|--------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| [`latest`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile) | [`latest-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine) |
| [`2.16.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.16.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.15.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.15.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.14.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.14.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.13.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.13.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.12.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.12.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.11.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.11.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.10.1`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.10.1-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.10.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.10.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.9.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.9.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.8.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.8.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.7.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.7.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.6.4`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.6.4-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.6.3`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.6.3-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.6.2`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.6.2-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.6.1`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.6.1-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.6.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.6.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.5.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.5.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.4.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.4.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.3.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.3.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.2.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.2.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.1.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.1.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`2.0.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`2.0.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| [`1.5.6`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)  | [`1.5.6-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)  |
| ~~[`1.5.5`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.5.5-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.5.4`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.5.4-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.5.3`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.5.3-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.5.2`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.5.2-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.5.1`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.5.1-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.5.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.5.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.4.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.4.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.3.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.3.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.2.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.2.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.1.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.1.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |
| ~~[`1.0.0`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile)~~  | ~~[`1.0.0-alpine`](https://raw.githubusercontent.com/vromero/activemq-artemis-docker/master/src/Dockerfile.alpine)~~  |

## 3. About this image

The ActiveMQ Artemis images come in two flavors, both equally supported :

- **Debian based**: the default one.
- **Alpine based**: much lighter.

All versions of ActiveMQ Artemis are provided for the time being but versions previous to 1.5.5 shall be considered deprecated and could be removed at any time.

This image shall not be considered production ready as is. If you plan to use this image in a production environment, fork the image in order to maintain stability as
the build is [reproducible](https://reproducible-builds.org/) in a best effort basis. Then at each rebase, make sure you tests the changes you are importing.

## 4. How to use this image

You can find how to run this image in the section *Running the image*. Beware as the default
configuration is not recommended for production usage, at the very least you'll want to set your own
login and password. This is described with detail in section *Setting the username and password*.
In case you also want to set some customized memory limits, this is described in
*Setting the memory values*.

ActiveMQ Artemis typically persists the queue state to disk. In order to leverage the most of your
disk ActiveMQ artemis might require some fine-tuning. The good news is that this process is
fully automated and its described in *Performing a performance journal test*.

JMX uses RMI and therefore random ports. This is extremely bad for automatization in Docker and
in general. For that reason its not supported for most of the use cases. However, when using this
image in orchestrators like Kubernetes you might want to connect from a sidecar where it
does make sense. How to enable JMX is described in section *Enabling JMX*.

The Jolokia console CORS header won't be a problem by default as it set to `*`, however if you want to
narrow it down for improved security don't miss the section *Settings the console's allow origin*.

In rare ocassions you might find the need of running ActiveMQ Artemis without security. This
is described in section *Disabling security*.

Some of the configurations mentioned above are scripted automations that modify the
configuration files. You might have your own configuration that you want to provide as a whole.
In that case disregard the aforementioned sections and find how to pass your own
configuration in section *Using external configuration files*.

If instead you want to use the configuration parameters and make some non-mayor changes to the
configuration you could use the mechanisms to apply some small transformations using XSLT
as described in section *Overriding parts of the configuration*.

## 5. Running the image

There are different methods to run a Docker image, from interactive Docker to Kubernetes and Docker
Compose. This documentation will cover only Docker with an interactive terminal mode. You should
refer to the appropriate documentation for more information around other execution methods.

To run ActiveMQ with AMQP, JMS and the web console open (if your are running `2.3.0` or later),
run the following command:

```console
docker run -it --rm \
  -p 8161:8161 \
  -p 61616:61616 \
  vromero/activemq-artemis
```  

After a few seconds you'll see in the output a block similar to:

    _        _               _
    / \  ____| |_  ___ __  __(_) _____
    / _ \|  _ \ __|/ _ \  \/  | |/  __/
    / ___ \ | \/ |_/  __/ |\/| | |\___ \
    /_/   \_\|   \__\____|_|  |_|_|/___ /
    Apache ActiveMQ Artemis x.x.x

    HH:mm:ss,SSS INFO  [...] AMQ101000: Starting ActiveMQ Artemis Server

At this point you can open the web server port at [`8161`](http://127.0.0.1:8161) and check the web console using
the default username and password of `artemis` / `simetraehcapa`.

### 5.1 Setting the username and password

If you wish to change the default username and password of `artemis` / `simetraehcapa`, you can do so with the `ARTEMIS_USERNAME` and `ARTEMIS_PASSWORD` environment variables:

```console
docker run -it --rm \
  -e ARTEMIS_USERNAME=myuser \
  -e ARTEMIS_PASSWORD=otherpassword \
  vromero/activemq-artemis
```

### 5.2 Setting the memory values

By default this image does leverage the new features that came in Java 8u131 related to memory ergonomics in containerized environments, more information about it [here](https://developers.redhat.com/blog/2017/03/14/java-inside-docker/).

It does use a `-XX:MaxRAMFraction=2` meaning that half of the memory made avaiable to the container will be used by the Java heap, leaving the other half for other types of Java memory and other OS purposes. However, in some
circumstances it might be advisable to fine tune the memory to manual values, in that case you can set the memory that you application needs by using the parameters `ARTEMIS_MIN_MEMORY` and `ARTEMIS_MAX_MEMORY`:

```console
docker run -it --rm \
  -e 'ARTEMIS_MIN_MEMORY=1512M' \
  -e 'ARTEMIS_MAX_MEMORY=3048M' \
  vromero/activemq-artemis
```

The previous example will launch Apache ActiveMQ Artemis in docker with 1512 MB of memory, with a maximum usage of 3048 MB of memory.
The format of the values passed is the same than the format used for the Java `-Xms` and `-Xmx` parameters and its documented [here](http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/java.html).

### 5.3 Performing a performance journal test

Different kinds of volumes need different values in fine tuning. In ActiveMQ Artemis the `journal-buffer-timeout` is oftentimes configured for this purpose.
**Since `1.5.3`** it is possible to calculate the optimal value automatically. This image supports this automation using the environment variable: `ARTEMIS_PERF_JOURNAL` with one of the following values:

| Value            | Description                                                       |
|------------------|-------------------------------------------------------------------|
|`AUTO` (default)  | Checks for the existence of a `.perf-journal-completed` file in the data volume, if it doesn't exist performs the calculation, applies the configuration and creates the file. |
|`NEVER`           | Never do the performance journal configuration                    |
|`ALWAYS`          | Always do the performance journal configuration                   |

It is safe to leave it as `AUTO` even for the casual usage of this image given that the image already have
incorporated a `.perf-journal-completed` for its internal directory used when no volume is mounted.
One example of execution with the performance journal calibration set to be executed always can be found
in the next listing:

```console
docker run -it --rm \
  -e ARTEMIS_PERF_JOURNAL=ALWAYS \
  vromero/activemq-artemis
```

### 5.4 Critical Analysis

Since 2.3.0 ActiveMQ Artemis can monitor *Queue delivery (add to the queue)*, *Journal storage* and *Paging operations* timings for anomalies in case there are IO errors or Memory issues (describe in detail [here](https://activemq.apache.org/components/artemis/documentation/latest/critical-analysis.html)).

The following properties can configure the critical analysis:

| Value                            | Description                                                                       |
|----------------------------------|-----------------------------------------------------------------------------------|
|`CRITICAL_ANALYZER`               | Enable or disable the critical analysis (default true or false)                   |
|`CRITICAL_ANALYZER_TIMEOUT`       | Timeout used to do the critical analysis (default 120000 milliseconds)            |
|`CRITICAL_ANALYZER_CHECK_PERIOD`  | Time used to check the response times (default half of critical-analyzer-timeout) |
|`CRITICAL_ANALYZER_POLICY`        | Should the server log, be halted or shutdown upon failures (default HALT or LOG)  |

### 5.5 Enabling JMX

Due to the JMX's nature, often with dynamics ports for RMI and the need having configure the public IP address to reach the RMI server.
It is discouraged to use JMX in Docker. Although in certain scenarios, it could be advisable, as when deploying in a
container orchestrator such as Kubernetes or Mesos, and deploying along side this container a side car. For such cases
the following environment variable could be used: `ENABLE_JMX`.

It is also possible to set the JMX port and the JMX RMI port with these two environment variables respectively: `JMX_PORT` (default: 1099) and `JMX_RMI_PORT` (default: 1098).

Given that JMX is intended for side cars, it is attached only to localhost and not protected with SSL. Likewise, its ports are not declared in the `Dockerfile`.

```console
docker run -it --rm \
  -e ENABLE_JMX=true \
  -e JMX_PORT=1199 \
  -e JMX_RMI_PORT=1198 \
  vromero/activemq-artemis
```

### 5.6 Using JSON Output

It can be oftentimes preferrable to have the log output structured in a parseable format. 
This image supports the usage of `org.jboss.logmanager.formatters.JsonFormatter` to format
the output. To enable it `LOG_FORMATTER=JSON` can be passed as environment variable.

```console
docker run -it --rm \
  -e LOG_FORMATTER=JSON \
  vromero/activemq-artemis
```
When used, the output will look similar to the following listing:

```console
     _        _               _
    / \  ____| |_  ___ __  __(_) _____
   / _ \|  _ \ __|/ _ \  \/  | |/  __/
  / ___ \ | \/ |_/  __/ |\/| | |\___ \
 /_/   \_\|   \__\____|_|  |_|_|/___ /
 Apache ActiveMQ Artemis 2.x.x

{"timestamp":"2020-04-25T09:43:17.222Z","sequence":0,"loggerClassName":"org.apache.activemq.artemis.integration.bootstrap.ActiveMQBootstrapLogger_$logger","loggerName":"org.apache.activemq.artemis.integration.bootstrap","level":"INFO","message":"AMQ101000: Starting ActiveMQ Artemis Server","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"354e0e2e67cb","processName":"Artemis","processId":78}
{"timestamp":"2020-04-25T09:43:17.408Z","sequence":1,"loggerClassName":"org.apache.activemq.artemis.core.server.ActiveMQServerLogger_$logger","loggerName":"org.apache.activemq.artemis.core.server","level":"INFO","message":"AMQ221000: live Message Broker is starting with configuration Broker Configuration (clustered=false,journalDirectory=data/journal,bindingsDirectory=data/bindings,largeMessagesDirectory=data/large-messages,pagingDirectory=data/paging)","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"354e0e2e67cb","processName":"Artemis","processId":78}
{"timestamp":"2020-04-25T09:43:17.648Z","sequence":2,"loggerClassName":"org.apache.activemq.artemis.core.server.ActiveMQServerLogger_$logger","loggerName":"org.apache.activemq.artemis.core.server","level":"INFO","message":"AMQ221012: Using AIO Journal","threadName":"main","threadId":1,"mdc":{},"ndc":"","hostName":"354e0e2e67cb","processName":"Artemis","processId":78}
```

### 5.7 Prometheus metrics

When using this image in a orchestrated environmnet like in Kubernetes. It is often useful to have metrics endpoints compatible
with prometheus to ease monitoring.

This image can export such metrics in port `9404` thanks to the integration with the Prometheus [JMX exporter](https://github.com/prometheus/jmx_exporter). In order to enable it the environmnet variable `ENABLE_JMX_EXPORTER` should
be present, it will also inderectly enable JMX as if `ENABLE_JMX` was set.

To see what is exported just:

```console
docker run -it --rm \
  -p9404:9404 \
  -e ENABLE_JMX_EXPORTER=true \
  vromero/activemq-artemis
```

And then in a different terminal run:

```console
curl http://127.0.0.1:9404
```

To obtain the following and more:

```
# HELP artemis_disk_scan_period How often to check for disk space usage, in milliseconds (org.apache.activemq.artemis<broker="0.0.0.0"><>DiskScanPeriod)
# TYPE artemis_disk_scan_period counter
artemis_disk_scan_period 5000.0
# HELP artemis_durable_delivering_count number of durable messages that this queue is currently delivering to its consumers (org.apache.activemq.artemis<broker="0.0.0.0", component=addresses, address="DLQ", subcomponent=queues, routing-type="anycast", queue="DLQ"><>DurableDeliveringCount)
# TYPE artemis_durable_delivering_count counter
artemis_durable_delivering_count{queue="DLQ",address="DLQ",} 0.0
artemis_durable_delivering_count{queue="ExpiryQueue",address="ExpiryQueue",} 0.0
# HELP artemis_journal_min_files Number of journal files to pre-create (org.apache.activemq.artemis<broker="0.0.0.0"><>JournalMinFiles)
# TYPE artemis_journal_min_files counter
artemis_journal_min_files 2.0
# HELP artemis_message_expiry_thread_priority Priority of the thread used to scan message expiration (org.apache.activemq.artemis<broker="0.0.0.0"><>MessageExpiryThreadPriority)
# TYPE artemis_message_expiry_thread_priority counter
artemis_message_expiry_thread_priority 3.0
# HELP artemis_messages_killed number of messages removed from this queue since it was created due to exceeding the max delivery attempts (org.apache.activemq.artemis<broker="0.0.0.0", component=addresses, address="DLQ", subcomponent=queues, routing-type="anycast", queue="DLQ"><>MessagesKilled)
# TYPE artemis_messages_killed counter
artemis_messages_killed{queue="DLQ",address="DLQ",} 0.0
artemis_messages_killed{queue="ExpiryQueue",address="ExpiryQueue",} 0.0
# HELP artemis_address_memory_usage_percentage Memory used by all the addresses on broker as a percentage of global maximum limit (org.apache.activemq.artemis<broker="0.0.0.0"><>AddressMemoryUsagePercentage)
# TYPE artemis_address_memory_usage_percentage counter
artemis_address_memory_usage_percentage 0.0
# HELP artemis_journal_sync_non_transactional Whether the journal is synchronized when receiving non-transactional datar (org.apache.activemq.artemis<broker="0.0.0.0"><>JournalSyncNonTransactional)
# TYPE artemis_journal_sync_non_transactional counter
artemis_journal_sync_non_transactional 1.0
# HELP artemis_journal_buffer_size Size of the internal buffer on the journal (org.apache.activemq.artemis<broker="0.0.0.0"><>JournalBufferSize)
# TYPE artemis_journal_buffer_size counter
artemis_journal_buffer_size 501760.0
# HELP artemis_journal_max_io Maximum number of write requests that can be in the AIO queue at any given time (org.apache.activemq.artemis<broker="0.0.0.0"><>JournalMaxIO)
# TYPE artemis_journal_max_io counter
artemis_journal_max_io 4096.0
```

In case you need more control over the metrics that are exported, you can mount a [jmx-exporter](https://github.com/prometheus/jmx_exporter)
configuration file in `/opt/jmx-exporter/etc-override` with the file name `jmx-exporter-config.yaml`.

### 5.8 Settings the console's allow origin

ActiveMQ Artemis console uses Jolokia. In the default vanilla non-docker installation Jolokia does set a CORS header to
allow only localhost. In the docker image this create problems as things are rarely accesed as localhost.

Therefore the docker image does set the CORS header to `*` by default. However there is a mechanism to narrow it
down to whatever value is best suited to you for improved security through the environmnet property: `JOLOKIA_ALLOW_ORIGIN`.

```console
docker run -it --rm \
  -e JOLOKIA_ALLOW_ORIGIN=192.168.1.1 \
  vromero/activemq-artemis
```

### 5.9 Overriding parts of the configuration

ActiveMQ Artemis support disabling the security using the element `<security-enabled>false</security-enabled>`
as described in the official [documentation](https://activemq.apache.org/artemis/docs/latest/security.html).
This docker image makes it simple to set that element using the environment property: `DISABLE_SECURITY`:

```console
docker run -it --rm \
  -e DISABLE_SECURITY=true \
  vromero/activemq-artemis
```

Please keep in mind no production system, possible no environment at all, should ever disable security.
Make sure you read the falacy number one of the [falacies of the distributed computing](https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing) before disabling the security.

### 5.10 Using external configuration files

It is possible to mount a whole artemis `etc` directory in this image in the volume `/var/lib/artemis/etc`.
Be careful as this might be an overkill for many situations where only small tweaks are necessary.  

When using this technique be aware that the configuration files of Artemis might change from version to version.
Generally speaking, when in need to configure Artemis beyond what it is offered by this image using environment
variables, it is recommended to use the partial override mechanism described in the next section.

### 5.11 Overriding parts of the configuration

The default ActiveMQ Artemis configuration can be partially modified, instead of completely replaced as in the previous section, using three mechanisms. Merge snippets, XSLT tranformations and entrypoint overrides.

**Merging snippets**

Multiple files with snippets of configuration can be dropped in the `/var/lib/artemis/etc-override` volume. Those configuration files must be named following the name convention `broker-{{num}}.xml` where `num` is a numeric representation of the snippet.
The configuration files will be *merged* with the default configuration. An alphabetical precedence of the file names will be considered for the merge and in case of collision the latest change will be treated as final.

For instance lets say that you want to add a diverts section, you could have a local directory, lets say `/var/artemis-data/etc-override`
where you could place a `broker-00.xml` file that looks like the following listing:

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
   <!-- from 1.0.0 to 1.5.5 the following line should be : <core xmlns="urn:activemq:core"> -->
   <core xmlns="urn:activemq:core" xsi:schemaLocation="urn:activemq:core ">
      <diverts>
         <divert name="order-divert">
            <routing-name>order-divert</routing-name>
            <address>orders</address>
            <forwarding-address>spyTopic</forwarding-address>
            <exclusive>false</exclusive>
         </divert>
      </diverts>
   </core>
</configuration>
```

Please notice the `core` element change along with the versions:

- `1.0.0` up to `1.5.5`: `<core xmlns="urn:activemq:core">`
- `2.0.0` onwards: `<core xmlns="urn:activemq:core" xsi:schemaLocation="urn:activemq:core ">`

**Configuration transformations**

For the use cases where instead of merging, the desired outcome is a deletion or some other kind of advanced transformation a file named `broker-00.xslt`
in `/var/lib/artemis/etc-override` is supported. For instance to delete the `jms` definitions that is present by default in the `broker.xml` file shown below:

```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
  ...
  <jms xmlns="urn:activemq:jms">
    <queue name="myfancyqueue"/>
    <queue name="myotherqueue"/>
  </jms>
  ...
</configuration>
```

A file name `broker-00.xslt` with content like the following listing, could be used:

```xslt
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:activemq="urn:activemq" xmlns:jms="urn:activemq:jms">

 <xsl:output omit-xml-declaration="yes"/>

    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="*[local-name()='jms']"/>
</xsl:stylesheet>
```

**Entrypoint Overrides**

Multiple shell scripts can be dropped in the `/var/lib/artemis/etc-override` volume. Those shell files must be named following the name convention `entrypoint-{{num}}.sh` where `num` is a numeric representation of the snippet.
The shell scripts will be *executed* in alphabetical precedence of the file names on startup of the docker container.   

A typical use case for using entrypoint overrides would be if you want to make a minor modification to a file which cannot be overriden using the 2 methods above and you do not want to expose the etc volume.


If you would like to see the final result of your transformations, execute the following:

```
docker run -it --rm \
  -v /var/artemis-data/override:/var/lib/artemis/etc-override \
  vromero/activemq-artemis \
  cat ../etc/broker.xml
```

### 5.12 Broker Config

ActiveMQ allows you to override key configuration values using [System properties](https://activemq.apache.org/artemis/docs/latest/configuration-index.html#System-properties).
This docker image has built in support to set these values by passing environment variables prefixed with BROKER_CONFIG to the docker image.  

Below is an example which overrides the global-max-size and disk-scan-period values
```
docker run -it --rm   -p 8161:8161 \
    -e BROKER_CONFIG_GLOBAL_MAX_SIZE=50000 \
    -e BROKER_CONFIG_DISK_SCAN_PERIOD=6000 \
    vromero/activemq-artemis
```

### 5.13 Environment Variables

Additionally, the following environment variables are supported

| Env Var         | Default          | Description                                                       |
|---------------- |----------------- |-------------------------------------------------------------------|
|JAVA_OPTS        |                  |Will pass additional java options to the artemis runtime           |

### 5.14 Mount points

| Mount point                      | Description                                                              |
|--------------------------------- |--------------------------------------------------------------------------|
|`/var/lib/artemis/data`           | Holds the data files used for storing persistent messages                |
|`/var/lib/artemis/etc`            | Holds the instance configuration files                                   |
|`/var/lib/artemis/etc-override`   | Holds the instance configuration files                                   |
|`/var/lib/artemis/lock`           | Holds the command line locks (typically not useful to mount)             |
|`/opt/jmx-exporter/etc-override`  | Holds the configuration file for jmx-exporter `jmx-exporter-config.yaml` |

### 5.15 Exposed ports

| Port    | Description                                                     |
|-------- |-----------------------------------------------------------------|
| `8161`  | Web Server                                                      |
| `9404`  | JMX Exporter                                                    |
| `61616` | Core,MQTT,AMQP,HORNETQ,STOMP,Openwire                           |
| `5445`  | HORNETQ,STOMP                                                   |
| `5672`  | AMQP                                                            |
| `1883`  | MQTT                                                            |
| `61613` | STOMP                                                           |

## 6. Running in orchestrators

At the moment only docker is directly supported for this image. However there is an attempt to create
a helm chart for Kubernetes and some configuration tuning for OpenShift.

### 6.1 Running in Kubernetes

ActiveMQ Artemis can leverage [JGroups](http://www.jgroups.org/) to discover the members of the cluster. And JGroups
can be extended with a plugin called [jgroups-kubernetes](https://github.com/jgroups-extras/jgroups-kubernetes/tree/0.9.3)
that allows JGroups to discover using Kubernetes. Both KUBE_PING (via Kubernetes API) and DNS_PING (using the SRV records of a
[Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#srv-records)) building blocks are
included to facilitate initial membership discovery.

[jgroups-kubernetes](https://github.com/jgroups-extras/jgroups-kubernetes/tree/0.9.3) version `0.9.3` is included in the
classpath of this image, however everything about the configuration of jgroups and jgroups-kubernetes is left to the user.

If you rather prefer a easier solution to run a cluster of ActiveMQ Artemis nodes, there is an attempt to create a Helm chart
by the same author of this image. It can be found [here](https://github.com/vromero/activemq-artemis-helm). It
does leverage `jgroups-kubernetes` in a transparent way.

### 6.2 OpenShift

OpenShift has diverted a bit from Kubernetes (e.g: automounts empty volumes in all declared volumes without
the user asking for it at all) and Docker (e.g: runs on an random user).

The biggest problem to run this image is the automount of empty directories because it empties the `etc` directory.
In order to restore it the environment variable `RESTORE_CONFIGURATION` has been created. It can be used as follows:

```bash
oc new-app --name=artemis vromero/activemq-artemis -e RESTORE_CONFIGURATION=true
```

## 7. License

View [license information](http://www.apache.org/licenses/LICENSE-2.0) for the software contained in this image.

## 8. User Feedback

### 8.1 Issues

If you have any problems with or questions about this image, please contact us through a [GitHub issue](https://github.com/vromero/activemq-artemis-docker/issues).

### 8.2 Contributing

You are invited to contribute new features, fixes, or updates, large or small; we are always thrilled to receive pull requests, and do our best to process them as fast as we can.

Before you start to code, we recommend discussing your plans through a [GitHub issue](https://github.com/vromero/activemq-artemis-docker/issues), especially for more ambitious contributions. This gives other contributors a chance to point you in the right direction, give you feedback on your design, and help you find out if someone else is working on the same thing.


================================================
FILE: src/Dockerfile
================================================
# ActiveMQ Artemis

##########################################################
## Build Image                                           #
##########################################################
ARG BASE_IMAGE
FROM openjdk:8u171-jdk-stretch as builder
LABEL maintainer="Victor Romero <victor.romero@gmail.com>"

ARG ACTIVEMQ_ARTEMIS_VERSION
ARG ACTIVEMQ_DISTRIBUTION_URL
ENV JMX_EXPORTER_VERSION=0.3.1
ENV JGROUPS_KUBERNETES_VERSION=0.9.3
ENV JAVAX_JSON_VERSION=1.1.4

# See https://github.com/hadolint/hadolint/wiki/DL4006
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

RUN apt-get -qq -o=Dpkg::Use-Pty=0 update && \
  apt-get -qq -o=Dpkg::Use-Pty=0 install -y --no-install-recommends \
    libaio1=0.3.110-3 \
    xmlstarlet=1.6.1-2 \
    jq=1.5+dfsg-1.3 \
    ca-certificates=20161130+nmu1+deb9u1 \
    wget=1.18-5+deb9u2 \
    ivy=2.4.0-3 && \
  rm -rf /var/lib/apt/lists/*

# Make sure pipes are considered to detemine success, see: https://github.com/hadolint/hadolint/wiki/DL4006
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Uncompress and validate
WORKDIR /opt
RUN if (echo "${ACTIVEMQ_DISTRIBUTION_URL}" | grep -Eq  ".zip\$" ) ; \
    then \
      mkdir tmp && \
      wget "${ACTIVEMQ_DISTRIBUTION_URL}" -P tmp/ && \
      unzip -d tmp -q "tmp/*.zip" && rm -f tmp/*.zip && ls -l tmp/ && \
        mv tmp/* ./apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION} && \
        ln -s "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" "/opt/apache-artemis" && \
        rmdir tmp; \
    elif test -n "${ACTIVEMQ_DISTRIBUTION_URL}" ; \
    then \
      echo "Only .zip format is supported when using ACTIVEMQ_DISTRIBUTION_URL" && \
      exit 2; \
    else \
      wget "https://repository.apache.org/content/repositories/releases/org/apache/activemq/apache-artemis/${ACTIVEMQ_ARTEMIS_VERSION}/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz" && \
      wget "https://repository.apache.org/content/repositories/releases/org/apache/activemq/apache-artemis/${ACTIVEMQ_ARTEMIS_VERSION}/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz.asc" && \
      wget "http://apache.org/dist/activemq/KEYS" && \
      gpg --no-tty --import "KEYS" && \
      gpg --no-tty "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz.asc" && \
      tar xfz "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz" && \
      ln -s "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" "/opt/apache-artemis" && \
      rm -f "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz" "KEYS" "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz.asc"; \
    fi

# Create broker instance
# Per recommendation of https://activemq.apache.org/artemis/docs/latest/perf-tuning.html : -XX:+AggressiveOpts -XX:+UseFastAccessorMethods -XX:+UseParallelOldGC 
WORKDIR /var/lib
RUN if test "${ACTIVEMQ_ARTEMIS_VERSION}" = "1.0.0" ; \
    then \
      echo n | "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/bin/artemis" create artemis \
        --home /opt/apache-artemis \
        --user artemis \
        --password simetraehcapa \
        --cluster-user artemisCluster \
        --cluster-password simetraehcaparetsulc ; \
    else \
      "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/bin/artemis" create artemis \
        --home /opt/apache-artemis \
        --user artemis \
        --password simetraehcapa \
        --role amq \
        --require-login \
        --cluster-user artemisCluster \
        --cluster-password simetraehcaparetsulc ; \
    fi 

# Using KUBE_PING 0.9.3. Can't upgrade to 1.x.x as Artemis uses JGroups 3.3.x 
# https://github.com/jgroups-extras/jgroups-kubernetes/issues/30
WORKDIR /opt/jgroupskubernetes
RUN java -jar /usr/share/java/ivy.jar -dependency org.jgroups.kubernetes kubernetes "${JGROUPS_KUBERNETES_VERSION}" -retrieve "[artifact]-[revision](-[classifier]).[ext]" -types jar && \
  java -jar /usr/share/java/ivy.jar -dependency org.jgroups.kubernetes dns "${JGROUPS_KUBERNETES_VERSION}" -retrieve "[artifact]-[revision](-[classifier]).[ext]" -types jar

# JsonFormatter to enable JSON logging #148
WORKDIR /opt/jsonformatter
RUN java -jar /usr/share/java/ivy.jar -dependency org.glassfish javax.json "${JAVAX_JSON_VERSION}" -retrieve "[artifact]-[revision](-[classifier]).[ext]" -types bundle

WORKDIR /var/lib/artemis/etc

# Log to tty to enable docker logs container-name
RUN sed -i "s/logger.handlers=.*/logger.handlers=CONSOLE/g" logging.properties

# Add JSON log handler
RUN echo "formatter.JSON=org.jboss.logmanager.formatters.JsonFormatter" | tee -a  logging.properties
RUN sed -i "s/-Xbootclasspath\/a:\"\(.*\)\"/-Xbootclasspath\/a:\"\1:\/opt\/apache-artemis\/lib\/javax.json-1.1.4.jar\"/g" /var/lib/artemis/bin/artemis

# --java-options doesn't seem to work across the board on all versions adding them manually
RUN sed -i "s/JAVA_ARGS=\"/JAVA_ARGS=\"-Djava.net.preferIPv4Addresses=true -Djava.net.preferIPv4Stack=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2 /g" ../etc/artemis.profile

# Ports are only exposed with an explicit argument, there is no need to binding
# the web console to localhost
RUN xmlstarlet ed -L -N amq="http://activemq.org/schema" \
    -u "/amq:broker/amq:web/@bind" \
    -v "http://0.0.0.0:8161" bootstrap.xml

# In a similar fashion the jolokia access is restricted to localhost only. Disabling
# this as in the natural environmnets for the image like Kubernetes this is problematic.
RUN if (echo "${ACTIVEMQ_ARTEMIS_VERSION}" | grep -Eq  "(2.[^0-3]\\.[0-9]|[^1-2]\\.[0-9]\\.[0-9]+)" ) ; then xmlstarlet ed --inplace --subnode "/restrict" --type elem -n "remote" jolokia-access.xml && xmlstarlet ed --inplace --subnode "/restrict/remote" --type elem -n host -v "0.0.0.0/0" jolokia-access.xml; fi

# Remove default values for memory in artemis profile in order to let the automatic
# Java ergonomics detection work https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ergonomics.html
RUN sed -i "s/-Xm[xs][^ \"]*//g" ../etc/artemis.profile

# For the casual run of the image make the docker-entrypoint-sh think 
# that the performance journal calibration is already completed
RUN if (echo "${ACTIVEMQ_ARTEMIS_VERSION}" | grep -Eq  "(1.5\\.[3-5]|[^1]\\.[0-9]\\.[0-9]+)" ) ; then touch /var/lib/artemis/data/.perf-journal-completed; fi

WORKDIR /opt/jmx-exporter
RUN wget "https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/${JMX_EXPORTER_VERSION}/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar" && \
  wget "https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/${JMX_EXPORTER_VERSION}/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar.sha1" && \
  echo "$(cat "jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar.sha1")" "jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar" | sha1sum -c - && \
  rm "jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar.sha1" && \
  ln -s "/opt/jmx-exporter/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar" "/opt/jmx-exporter/jmx_prometheus_javaagent.jar"

COPY assets/jmx-exporter-config.yaml /opt/jmx-exporter/etc/

##########################################################
## Run Image                                             #
##########################################################
ARG BASE_IMAGE
# hadolint ignore=DL3006
FROM $BASE_IMAGE
LABEL maintainer="Victor Romero <victor.romero@gmail.com>"
ARG ACTIVEMQ_ARTEMIS_VERSION
ENV ACTIVEMQ_ARTEMIS_VERSION=$ACTIVEMQ_ARTEMIS_VERSION

# add user and group for artemis
RUN groupadd -g 1000 -r artemis && useradd -r -u 1000 -g artemis artemis

RUN apt-get -qq -o=Dpkg::Use-Pty=0 update && \
  apt-get -qq -o=Dpkg::Use-Pty=0 install -y --no-install-recommends \
    libaio1=0.3.110-3 \
    xmlstarlet=1.6.1-2 \
    jq=1.5+dfsg-1.3 \
    gettext-base=0.19.8.1-2+deb9u1 \
    dumb-init=1.2.0-1 \
    procps=2:3.3.12-3+deb9u1 && \
  rm -rf /var/lib/apt/lists/*

COPY --from=builder "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}"
COPY --from=builder "/var/lib/artemis" "/var/lib/artemis"
COPY --from=builder "/opt/jmx-exporter" "/opt/jmx-exporter"
COPY --from=builder "/opt/jgroupskubernetes/*" "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/lib/"
COPY --from=builder "/opt/jsonformatter/*" "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/lib/"

# To enable RESTORE_CONFIGURATION
COPY --from=builder "/var/lib/artemis/etc" "/var/lib/artemis/etc-backup"

RUN ln -s "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" /opt/apache-artemis && chmod 755 /opt/apache-artemis
RUN chown -R artemis.artemis /var/lib/artemis
RUN chown -R artemis.artemis /opt/jmx-exporter

RUN mkdir -p /opt/assets
COPY assets/merge.xslt /opt/assets
COPY assets/enable-jmx.xml /opt/assets
COPY assets/semver2.sh /usr/local/bin/semver

# Web Server
EXPOSE 8161

# JMX Exporter
EXPOSE 9404

# Port for CORE,MQTT,AMQP,HORNETQ,STOMP,OPENWIRE
EXPOSE 61616

# Port for HORNETQ,STOMP
EXPOSE 5445

# Port for AMQP
EXPOSE 5672

# Port for MQTT
EXPOSE 1883

#Port for STOMP
EXPOSE 61613

WORKDIR /var/lib/artemis/bin

USER artemis

RUN mkdir /var/lib/artemis/lock

# Expose some outstanding folders
VOLUME ["/var/lib/artemis/data"]
VOLUME ["/var/lib/artemis/tmp"]
VOLUME ["/var/lib/artemis/etc"]
VOLUME ["/var/lib/artemis/etc-override"]
VOLUME ["/var/lib/artemis/lock"]
VOLUME ["/opt/jmx-exporter/etc-override"]

COPY assets/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["artemis-server"]


================================================
FILE: src/Dockerfile.alpine
================================================
# ActiveMQ Artemis

##########################################################
## Build Image                                           #
##########################################################
ARG BASE_IMAGE
FROM openjdk:8u171-jdk-stretch as builder
LABEL maintainer="Victor Romero <victor.romero@gmail.com>"

ARG ACTIVEMQ_ARTEMIS_VERSION
ARG ACTIVEMQ_DISTRIBUTION_URL
ENV JMX_EXPORTER_VERSION=0.3.1
ENV JGROUPS_KUBERNETES_VERSION=0.9.3
ENV JAVAX_JSON_VERSION=1.1.4

# add user and group for artemis
RUN groupadd -r artemis && useradd -r -s /bin/false -g artemis artemis

RUN apt-get -qq -o=Dpkg::Use-Pty=0 update && \
  apt-get -qq -o=Dpkg::Use-Pty=0 install -y --no-install-recommends \
    libaio1=0.3.110-3 \
    xmlstarlet=1.6.1-2 \
    jq=1.5+dfsg-1.3 \
    ca-certificates=20161130+nmu1+deb9u1 \
    wget=1.18-5+deb9u2 \
    ivy=2.4.0-3 && \
  rm -rf /var/lib/apt/lists/*

# Make sure pipes are considered to detemine success, see: https://github.com/hadolint/hadolint/wiki/DL4006
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

# Uncompress and validate
WORKDIR /opt
RUN if (echo "${ACTIVEMQ_DISTRIBUTION_URL}" | grep -Eq  ".zip\$" ) ; \
    then \
      mkdir tmp && \
      wget "${ACTIVEMQ_DISTRIBUTION_URL}" -P tmp/ && \
      unzip -d tmp -q "tmp/*.zip" && rm -f tmp/*.zip && ls -l tmp/ && \
        mv tmp/* ./apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION} && \
        ln -s "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" "/opt/apache-artemis" && \
        rmdir tmp; \
    elif test -n "${ACTIVEMQ_DISTRIBUTION_URL}" ; \
    then \
      echo "Only .zip format is supported when using ACTIVEMQ_DISTRIBUTION_URL" && \
      exit 2; \
    else \
      wget "https://repository.apache.org/content/repositories/releases/org/apache/activemq/apache-artemis/${ACTIVEMQ_ARTEMIS_VERSION}/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz" && \
      wget "https://repository.apache.org/content/repositories/releases/org/apache/activemq/apache-artemis/${ACTIVEMQ_ARTEMIS_VERSION}/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz.asc" && \
      wget "http://apache.org/dist/activemq/KEYS" && \
      gpg --no-tty --import "KEYS" && \
      gpg --no-tty "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz.asc" && \
      tar xfz "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz" && \
      ln -s "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" "/opt/apache-artemis" && \
      rm -f "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz" "KEYS" "apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}-bin.tar.gz.asc"; \
    fi

# Create broker instance
# Per recommendation of https://activemq.apache.org/artemis/docs/latest/perf-tuning.html : -XX:+AggressiveOpts -XX:+UseFastAccessorMethods -XX:+UseParallelOldGC 
WORKDIR /var/lib
RUN if test "${ACTIVEMQ_ARTEMIS_VERSION}" = "1.0.0" ; \
    then \
      echo n | "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/bin/artemis" create artemis \
        --home /opt/apache-artemis \
        --user artemis \
        --password simetraehcapa \
        --cluster-user artemisCluster \
        --cluster-password simetraehcaparetsulc ; \
    else \
      "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/bin/artemis" create artemis \
        --home /opt/apache-artemis \
        --user artemis \
        --password simetraehcapa \
        --role amq \
        --require-login \
        --cluster-user artemisCluster \
        --cluster-password simetraehcaparetsulc ; \
    fi 

# Using KUBE_PING 0.9.3. Can't upgrade to 1.x.x as Artemis uses JGroups 3.3.x 
# https://github.com/jgroups-extras/jgroups-kubernetes/issues/30
WORKDIR /opt/jgroupskubernetes
RUN java -jar /usr/share/java/ivy.jar -dependency org.jgroups.kubernetes kubernetes "${JGROUPS_KUBERNETES_VERSION}" -retrieve "[artifact]-[revision](-[classifier]).[ext]" -types jar && \
    java -jar /usr/share/java/ivy.jar -dependency org.jgroups.kubernetes dns "${JGROUPS_KUBERNETES_VERSION}" -retrieve "[artifact]-[revision](-[classifier]).[ext]" -types jar

# JsonFormatter to enable JSON logging #148
WORKDIR /opt/jsonformatter
RUN java -jar /usr/share/java/ivy.jar -dependency org.glassfish javax.json "${JAVAX_JSON_VERSION}" -retrieve "[artifact]-[revision](-[classifier]).[ext]" -types bundle

# JsonFormatter to enable JSON logging #148
WORKDIR /opt/jsonformatter
RUN java -jar /usr/share/java/ivy.jar -dependency org.glassfish javax.json "${JAVAX_JSON_VERSION}" -retrieve "[artifact]-[revision](-[classifier]).[ext]" -types bundle

WORKDIR /var/lib/artemis/etc

# Log to tty to enable docker logs container-name
RUN sed -i "s/logger.handlers=.*/logger.handlers=CONSOLE/g" logging.properties

# Add JSON log handler
RUN echo "formatter.JSON=org.jboss.logmanager.formatters.JsonFormatter" | tee -a  logging.properties
RUN sed -i "s/-Xbootclasspath\/a:\"\(.*\)\"/-Xbootclasspath\/a:\"\1:\/opt\/apache-artemis\/lib\/javax.json-1.1.4.jar\"/g" /var/lib/artemis/bin/artemis

# --java-options doesn't seem to work across the board on all versions adding them manually
RUN sed -i "s/JAVA_ARGS=\"/JAVA_ARGS=\"-Djava.net.preferIPv4Addresses=true -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2 /g" ../etc/artemis.profile

# Ports are only exposed with an explicit argument, there is no need to binding
# the web console to localhost
RUN xmlstarlet ed -L -N amq="http://activemq.org/schema" \
    -u "/amq:broker/amq:web/@bind" \
    -v "http://0.0.0.0:8161" bootstrap.xml

# In a similar fashion the jolokia access is restricted to localhost only. Disabling
# this as in the natural environmnets for the image like Kubernetes this is problematic.
RUN if (echo "${ACTIVEMQ_ARTEMIS_VERSION}" | grep -Eq  "(2.[^0-3]\\.[0-9]|[^1-2]\\.[0-9]\\.[0-9]+)" ) ; then xmlstarlet ed --inplace --subnode "/restrict" --type elem -n "remote" jolokia-access.xml && xmlstarlet ed --inplace --subnode "/restrict/remote" --type elem -n host -v "0.0.0.0/0" jolokia-access.xml; fi

# Remove default values for memory in artemis profile in order to let the automatic
# Java ergonomics detection work https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ergonomics.html
RUN sed -i "s/-Xm[xs][^ \"]*//g" ../etc/artemis.profile

# For the casual run of the image make the docker-entrypoint-sh think 
# that the performance journal calibration is already completed
RUN if (echo "${ACTIVEMQ_ARTEMIS_VERSION}" | grep -Eq  "(1.5\\.[3-5]|[^1]\\.[0-9]\\.[0-9]+)" ) ; then touch /var/lib/artemis/data/.perf-journal-completed; fi

WORKDIR /opt/jmx-exporter
RUN wget "https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/${JMX_EXPORTER_VERSION}/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar" && \
  wget "https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/${JMX_EXPORTER_VERSION}/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar.sha1" && \
  echo "$(cat "jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar.sha1")" "jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar" | sha1sum -c - && \
  rm "jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar.sha1" && \
  ln -s "/opt/jmx-exporter/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar" "/opt/jmx-exporter/jmx_prometheus_javaagent.jar"
COPY assets/jmx-exporter-config.yaml /opt/jmx-exporter/etc/

##########################################################
## Run Image                                             #
##########################################################
ARG BASE_IMAGE
# hadolint ignore=DL3006
FROM $BASE_IMAGE
LABEL maintainer="Victor Romero <victor.romero@gmail.com>"
ARG ACTIVEMQ_ARTEMIS_VERSION
ENV ACTIVEMQ_ARTEMIS_VERSION=$ACTIVEMQ_ARTEMIS_VERSION

# add user and group for artemis
RUN addgroup -g 1000 -S artemis && adduser -u 1000 -S -G artemis artemis

# Sadly this line is likely to fail every so often, see: https://medium.com/@stschindler/the-problem-with-docker-and-alpines-package-pinning-18346593e891
# Still versions are pinned to maintain some small level of https://reproducible-builds.org/
RUN apk add --no-cache \
  libaio=0.3.111-r0 \
  xmlstarlet=1.6.1-r0 \
  jq=1.6-r0 \
  dumb-init=1.2.2-r1 \
  sed=4.5-r0 \
  gettext=0.19.8.1-r4

COPY --from=builder "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}"
COPY --from=builder "/var/lib/artemis" "/var/lib/artemis"
COPY --from=builder "/opt/jmx-exporter" "/opt/jmx-exporter"
COPY --from=builder "/opt/jgroupskubernetes/*" "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/lib/"
COPY --from=builder "/opt/jsonformatter/*" "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}/lib/"

# To enable RESTORE_CONFIGURATION
COPY --from=builder "/var/lib/artemis/etc" "/var/lib/artemis/etc-backup"

RUN ln -s "/opt/apache-artemis-${ACTIVEMQ_ARTEMIS_VERSION}" /opt/apache-artemis
RUN chown -R artemis.artemis /var/lib/artemis 
RUN chown -R artemis.artemis /opt/jmx-exporter

RUN mkdir -p /opt/assets
COPY assets/merge.xslt /opt/assets
COPY assets/enable-jmx.xml /opt/assets
COPY assets/semver2.sh /usr/local/bin/semver

# Web Server
EXPOSE 8161

# JMX Exporter
EXPOSE 9404

# Port for CORE,MQTT,AMQP,HORNETQ,STOMP,OPENWIRE
EXPOSE 61616

# Port for HORNETQ,STOMP
EXPOSE 5445

# Port for AMQP
EXPOSE 5672

# Port for MQTT
EXPOSE 1883

#Port for STOMP
EXPOSE 61613

WORKDIR /var/lib/artemis/bin

USER artemis

RUN mkdir /var/lib/artemis/lock

# Expose some outstanding folders
VOLUME ["/var/lib/artemis/data"]
VOLUME ["/var/lib/artemis/tmp"]
VOLUME ["/var/lib/artemis/etc"]
VOLUME ["/var/lib/artemis/etc-override"]
VOLUME ["/var/lib/artemis/lock"]

COPY assets/docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["artemis-server"]


================================================
FILE: src/assets/docker-entrypoint.sh
================================================
#!/bin/sh
set -e

BROKER_HOME=/var/lib/artemis
OVERRIDE_PATH=$BROKER_HOME/etc-override
CONFIG_PATH=$BROKER_HOME/etc
export BROKER_HOME OVERRIDE_PATH CONFIG_PATH

# Prepends a value in the JAVA_ARGS of artemis.profile
# $1 New string to be prepended to JAVA_ARGS
# $2 Deduplication string
prepend_java_arg() {
  sed -i "\#$1#!s#^\([[:space:]]\)*JAVA_ARGS=\"#\\1JAVA_ARGS=\"$2 #g" $CONFIG_PATH/artemis.profile
}

# Returns true if the semver version in $1 is greater 
# of equal than the one passed in $2
# $1 input version
# $2 comparison version
semver_greater_or_equal_than() {
  # shellcheck disable=SC2046
  test $(semver "${1}" "${2}") -ge 0
  return 
}

# In case this is running in a non standard system that automounts
# empty volumes like OpenShift, restore the configuration into the 
# volume
if [ "$RESTORE_CONFIGURATION" ] && [ -z "$(ls -A ${CONFIG_PATH})" ]; then
  cp -R "${CONFIG_PATH}"-backup/* "${CONFIG_PATH}"
  echo Configuration restored
fi

# Update logger if the argument is passed
if [ "$LOG_FORMATTER" = "JSON" ]; then
    sed -i "s/handler.CONSOLE.formatter=.*/handler.CONSOLE.formatter=JSON/g" ../etc/logging.properties
fi

# Never use in a production environment
if [ "$DISABLE_SECURITY" ]; then
    xmlstarlet ed -L \
      -N activemq="urn:activemq" \
      -N core="urn:activemq:core" \
      --subnode "/activemq:configuration/core:core[not(core:security-enabled)]" \
      -t elem \
      -n "security-enabled" \
      -v "false" ../etc/broker.xml 
fi

# Set the broker name to the host name to ease experience for external monitors and the console
if semver_greater_or_equal_than "${ACTIVEMQ_ARTEMIS_VERSION}" 1.3.0 ; then
  xmlstarlet ed -L \
    -N activemq="urn:activemq" \
    -N core="urn:activemq:core" \
    -u "/activemq:configuration/core:core/core:name" \
    -v "$(hostname)" ../etc/broker.xml
fi

# Update users and roles with if username and password is passed as argument
if [ "$ARTEMIS_USERNAME" ] && [ "$ARTEMIS_PASSWORD" ]; then

  # Roles update

  # 2.0.0 and later are set using the cli with a running broker
  if semver_greater_or_equal_than "${ACTIVEMQ_ARTEMIS_VERSION}" 1.2.0 ; then
    # From 1.2.0 on became group=users and we still set it with sed
    sed -i "s/amq[ ]*=.*/amq=$ARTEMIS_USERNAME\\n/g" ../etc/artemis-roles.properties
  else
    # From 1.0.0 up to 1.1.0 the artemis roles file was user=groups
    sed -i "s/artemis=amq/$ARTEMIS_USERNAME=amq\\n/g" ../etc/artemis-roles.properties
  fi

  # Users update

  # 2.16.0 and later are set using the cli with a running broker
  if semver_greater_or_equal_than "${ACTIVEMQ_ARTEMIS_VERSION}" 2.15.0 ; then
    HASHED_PASSWORD=$(${BROKER_HOME}/bin/artemis mask --hash "${ARTEMIS_PASSWORD}" | cut -d " " -f 2)
    sed -i "s/artemis[ ]*=.*/$ARTEMIS_USERNAME=ENC($HASHED_PASSWORD)\\n/g" ../etc/artemis-users.properties
  elif semver_greater_or_equal_than "${ACTIVEMQ_ARTEMIS_VERSION}" 1.5.0 ; then
    # 1.5.0 to 2.14.0 modified the users file directly and therefore didn't need a running broker
    if ${BROKER_HOME}/bin/artemis user list | grep -Eq "\"${INITIAL_ARTEMIS_USERNAME}\"" ; then
      $BROKER_HOME/bin/artemis user rm --user "${INITIAL_ARTEMIS_USERNAME}"
    fi
    if ${BROKER_HOME}/bin/artemis user list | grep -Eq "\"${ARTEMIS_USERNAME}\"" ; then
      $BROKER_HOME/bin/artemis user rm --user "$ARTEMIS_USERNAME"
    fi
    $BROKER_HOME/bin/artemis user add --user "$ARTEMIS_USERNAME" --password "$ARTEMIS_PASSWORD" --role amq
  else
    # 1.0.0 to 1.4.0 modify the file directly with the old format
    sed -i "s/artemis[ ]*=.*/$ARTEMIS_USERNAME=$ARTEMIS_PASSWORD\\n/g" ../etc/artemis-users.properties
  fi
fi

# Update min memory if the argument is passed
if [ "$ARTEMIS_MIN_MEMORY" ]; then
  prepend_java_arg "-Xms" "-Xms$ARTEMIS_MIN_MEMORY"
fi

# Update max memory if the argument is passed
if [ "$ARTEMIS_MAX_MEMORY" ]; then
  prepend_java_arg "-Xmx" "-Xmx$ARTEMIS_MAX_MEMORY"
fi

# Support extra java opts from JAVA_OPTS env
if [ "$JAVA_OPTS" ]; then
  prepend_java_arg "$JAVA_OPTS" "$JAVA_OPTS"
fi

mergeXmlFiles() {
  xmlstarlet tr /opt/assets/merge.xslt -s replace=true -s with="$2" "$1" > /tmp/broker-merge.xml
  mv /tmp/broker-merge.xml "$3"
}

files=$(find $OVERRIDE_PATH -name "broker*" -type f | sort -u );
if [ ${#files[@]} ]; then
  for f in $files; do
    fnoext=${f%.*}
    if [ -f "$fnoext.xslt" ]; then
      xmlstarlet tr "$fnoext.xslt" $CONFIG_PATH/broker.xml > /tmp/broker-tr.xml
      mv /tmp/broker-tr.xml $CONFIG_PATH/broker.xml
    fi
    if [ -f "$fnoext.xml" ]; then
      mergeXmlFiles "$CONFIG_PATH/broker.xml" "$fnoext.xml" "$CONFIG_PATH/broker.xml"
    fi
  done
else
  echo No configuration snippets found
fi

if [ "$ENABLE_JMX" ] || [ "$ENABLE_JMX_EXPORTER" ]; then
  prepend_java_arg "com.sun.management.jmxremote" "-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=${JMX_PORT:-1099} -Dcom.sun.management.jmxremote.rmi.port=${JMX_RMI_PORT:-1098} -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
  mergeXmlFiles "$CONFIG_PATH/broker.xml" /opt/assets/enable-jmx.xml "$CONFIG_PATH/broker.xml"
fi

if [ "$ENABLE_JMX_EXPORTER" ]; then
  if [ -f /opt/jmx-exporter/etc-override/jmx-exporter-config.yaml ]; then
    cp /opt/jmx-exporter/etc-override/jmx-exporter-config.yaml /opt/jmx-exporter/etc/jmx-exporter-config.yaml
  fi
  prepend_java_arg "jmx_prometheus_javaagent.jar" "-javaagent:\\/opt\\/jmx-exporter\\/jmx_prometheus_javaagent.jar=9404:\\/opt\\/jmx-exporter\\/etc\\/jmx-exporter-config.yaml"
fi

if [ -n "$CRITICAL_ANALYZER" ]; then
  xmlstarlet ed -L \
    -N activemq="urn:activemq" \
    -N core="urn:activemq:core" \
    -u "/activemq:configuration/core:core/core:critical-analyzer" \
    -v "$CRITICAL_ANALYZER" ../etc/broker.xml
fi

if [ -n "$CRITICAL_ANALYZER_TIMEOUT" ]; then
  xmlstarlet ed -L \
    -N activemq="urn:activemq" \
    -N core="urn:activemq:core" \
    -u "/activemq:configuration/core:core/core:critical-analyzer-timeout" \
    -v "${CRITICAL_ANALYZER_TIMEOUT}" ../etc/broker.xml
fi

if [ -n "$CRITICAL_ANALYZER_CHECK_PERIOD" ]; then
  xmlstarlet ed -L \
    -N activemq="urn:activemq" \
    -N core="urn:activemq:core" \
    -u "/activemq:configuration/core:core/core:critical-analyzer-check-period" \
    -v "${CRITICAL_ANALYZER_CHECK_PERIOD}" ../etc/broker.xml
fi

if [ -n "$CRITICAL_ANALYZER_POLICY" ]; then
  xmlstarlet ed -L \
    -N activemq="urn:activemq" \
    -N core="urn:activemq:core" \
    -u "/activemq:configuration/core:core/core:critical-analyzer-policy" \
    -v "${CRITICAL_ANALYZER_POLICY}" ../etc/broker.xml
fi

if [ -e /var/lib/artemis/etc/jolokia-access.xml ]; then
  xmlstarlet ed --inplace -u '/restrict/cors/allow-origin' -v "${JOLOKIA_ALLOW_ORIGIN:-*}" /var/lib/artemis/etc/jolokia-access.xml
fi

performanceJournal() {
  perfJournalConfiguration=${ARTEMIS_PERF_JOURNAL:-AUTO}
  if [ "$perfJournalConfiguration" = "AUTO" ] || [ "$perfJournalConfiguration" = "ALWAYS" ]; then

    if [ "$perfJournalConfiguration" = "AUTO" ] && [ -e /var/lib/artemis/data/.perf-journal-completed ]; then
      echo "Volume's journal buffer already fine tuned"
      return
    fi

    echo "Calculating performance journal ... "
    RECOMMENDED_JOURNAL_BUFFER=$("./artemis" "perf-journal" | grep "<journal-buffer-timeout" | xmlstarlet sel -t -c '/journal-buffer-timeout/text()' || true)
    if [ -z "$RECOMMENDED_JOURNAL_BUFFER" ]; then
      echo "There was an error calculating the performance journal, gracefully handling it"
      return
    fi

    xmlstarlet ed -L \
      -N activemq="urn:activemq" \
      -N core="urn:activemq:core" \
      -u "/activemq:configuration/core:core/core:journal-buffer-timeout" \
      -v "$RECOMMENDED_JOURNAL_BUFFER" ../etc/broker.xml
      echo "$RECOMMENDED_JOURNAL_BUFFER"

    if [ "$perfJournalConfiguration" = "AUTO" ]; then
      touch /var/lib/artemis/data/.perf-journal-completed
    fi
  else
    echo "Skipping performance journal tuning as per user request"
  fi
}

if semver_greater_or_equal_than "${ACTIVEMQ_ARTEMIS_VERSION}" 1.5.3 ; then 
  performanceJournal
else
  echo "Ignoring any performance journal parameter as version predates it: ${ACTIVEMQ_ARTEMIS_VERSION}"
fi

# Add BROKER_CONFIGS env variable to startup options
prepend_java_arg "BROKER_CONFIGS" "\$BROKER_CONFIGS"

# Loop through all BROKER_CONFIG_... and convert to java system properties
env|grep -E "^BROKER_CONFIG_"|sed -e 's/BROKER_CONFIG_//g' >/tmp/brokerconfigs.txt
while read -r config
do
  PARAM=${config%%=*}
  PARAM_CAMEL_CASE=$(echo "$PARAM"|sed -r 's/./\L&/g; s/(^|-|_)(\w)/\U\2/g; s/./\L&/')
  VALUE=${config#*=}
  BROKER_CONFIGS="${BROKER_CONFIGS} -Dbrokerconfig.${PARAM_CAMEL_CASE}=${VALUE}"
done < /tmp/brokerconfigs.txt
rm -f /tmp/brokerconfigs.txt
export BROKER_CONFIGS

files=$(find $OVERRIDE_PATH -name "entrypoint*.sh" -type f | sort -u );
if [ ${#files[@]} ]; then
  for f in $files; do
    echo "Processing entrypoint override: $f"
    /bin/sh "$f"
  done
fi

if [ "$1" = 'artemis-server' ]; then
  exec dumb-init -- sh ./artemis run
fi

exec "$@"


================================================
FILE: src/assets/enable-jmx.xml
================================================
<?xml version="1.0"?>

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">

  <core xmlns="urn:activemq:core">
    <jmx-management-enabled>true</jmx-management-enabled>
  </core>

</configuration>


================================================
FILE: src/assets/jmx-exporter-config.yaml
================================================
---
lowercaseOutputName: true
lowercaseOutputLabelNames: true
rules:
  - pattern: "^org.apache.activemq.artemis<broker=\"([^\"]*)\"><>([^:]*):\\s(.*)"
    attrNameSnakeCase: true
    name: artemis_$2
    type: COUNTER
  - pattern: "^org.apache.activemq.artemis<broker=\"([^\"]*)\",\\s*component=addresses,\\s*address=\"([^\"]*)\"><>([^:]*):\\s(.*)"
    attrNameSnakeCase: true
    name: artemis_$3
    type: COUNTER
    labels:
        address: $2
  - pattern: "^org.apache.activemq.artemis<broker=\"([^\"]*)\",\\s*component=addresses,\\s*address=\"([^\"]*)\",\\s*subcomponent=(queue|topic)s,\\s*routing-type=\"([^\"]*)\",\\s*(queue|topic)=\"([^\"]*)\"><>([^: ]*):\\s(.*)"
    attrNameSnakeCase: true
    name: artemis_$7
    type: COUNTER
    labels:
        address: $2
        "$5": $6


================================================
FILE: src/assets/merge.xslt
================================================
<?xml version="1.0"?>

<!--
   Merging two XML files
   Version 1.6
   LGPL (c) Oliver Becker, 2002-07-05
   obecker@informatik.hu-berlin.de
-->

<xslt:transform version="1.0"
                xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
                xmlns:m="http://informatik.hu-berlin.de/merge"
                exclude-result-prefixes="m">


<!-- Normalize the contents of text, comment, and processing-instruction
     nodes before comparing?
     Default: yes -->
<xslt:param name="normalize" select="'yes'" />

<!-- Don't merge elements with this (qualified) name -->
<xslt:param name="dontmerge" />

<!-- If set to true, text nodes in file1 will be replaced -->
<xslt:param name="replace" select="false()" />

<!-- Variant 1: Source document looks like
     <?xml version="1.0"?>
     <merge xmlns="http://informatik.hu-berlin.de/merge">
        <file1>file1.xml</file1>
        <file2>file2.xml</file2>
     </merge>
     The transformation sheet merges file1.xml and file2.xml.
-->
<xslt:template match="m:merge" >
   <xslt:variable name="file1" select="string(m:file1)" />
   <xslt:variable name="file2" select="string(m:file2)" />
   <xslt:message>
      <xslt:text />Merging '<xslt:value-of select="$file1" />
      <xslt:text />' and '<xslt:value-of select="$file2"/>'<xslt:text />
   </xslt:message>
   <xslt:if test="$file1='' or $file2=''">
      <xslt:message terminate="yes">
         <xslt:text>No files to merge specified</xslt:text>
      </xslt:message>
   </xslt:if>
   <xslt:call-template name="m:merge">
      <xslt:with-param name="nodes1" select="document($file1,/*)/node()" />
      <xslt:with-param name="nodes2" select="document($file2,/*)/node()" />
   </xslt:call-template>
</xslt:template>


<!-- Variant 2:
     The transformation sheet merges the source document with the
     document provided by the parameter "with".
-->
<xslt:param name="with" />

<xslt:template match="*">
   <xslt:message>
      <xslt:text />Merging input with '<xslt:value-of select="$with"/>
      <xslt:text>'</xslt:text>
   </xslt:message>
   <xslt:if test="string($with)=''">
      <xslt:message terminate="yes">
         <xslt:text>No input file specified (parameter 'with')</xslt:text>
      </xslt:message>
   </xslt:if>

   <xslt:call-template name="m:merge">
      <xslt:with-param name="nodes1" select="/node()" />
      <xslt:with-param name="nodes2" select="document($with,/*)/node()" />
   </xslt:call-template>
</xslt:template>


<!-- ============================================================== -->

<!-- The "merge" template -->
<xslt:template name="m:merge">
   <xslt:param name="nodes1" />
   <xslt:param name="nodes2" />

   <xslt:choose>
      <!-- Is $nodes1 resp. $nodes2 empty? -->
      <xslt:when test="count($nodes1)=0">
         <xslt:copy-of select="$nodes2" />
      </xslt:when>
      <xslt:when test="count($nodes2)=0">
         <xslt:copy-of select="$nodes1" />
      </xslt:when>

      <xslt:otherwise>
         <!-- Split $nodes1 and $nodes2 -->
         <xslt:variable name="first1" select="$nodes1[1]" />
         <xslt:variable name="rest1" select="$nodes1[position()!=1]" />
         <xslt:variable name="first2" select="$nodes2[1]" />
         <xslt:variable name="rest2" select="$nodes2[position()!=1]" />
         <!-- Determine type of node $first1 -->
         <xslt:variable name="type1">
            <xslt:apply-templates mode="m:detect-type" select="$first1" />
         </xslt:variable>

         <!-- Compare $first1 and $first2 -->
         <xslt:variable name="diff-first">
            <xslt:call-template name="m:compare-nodes">
               <xslt:with-param name="node1" select="$first1" />
               <xslt:with-param name="node2" select="$first2" />
            </xslt:call-template>
         </xslt:variable>

         <xslt:choose>
            <!-- $first1 != $first2 -->
            <xslt:when test="$diff-first='!'">
               <!-- Compare $first1 and $rest2 -->
               <xslt:variable name="diff-rest">
                  <xslt:for-each select="$rest2">
                     <xslt:call-template name="m:compare-nodes">
                        <xslt:with-param name="node1" select="$first1" />
                        <xslt:with-param name="node2" select="." />
                     </xslt:call-template>
                  </xslt:for-each>
               </xslt:variable>

               <xslt:choose>
                  <!-- $first1 is in $rest2 and
                       $first1 is *not* an empty text node  -->
                  <xslt:when test="contains($diff-rest,'=') and
                                      not($type1='text' and
                                          normalize-space($first1)='')">
                     <!-- determine position of $first1 in $nodes2
                          and copy all preceding nodes of $nodes2 -->
                     <xslt:variable name="pos"
                           select="string-length(substring-before(
                                                $diff-rest,'=')) + 2" />
                     <xslt:copy-of
                           select="$nodes2[position() &lt; $pos]" />
                     <!-- merge $first1 with its equivalent node -->
                     <xslt:choose>
                        <!-- Elements: merge -->
                        <xslt:when test="$type1='element'">
                           <xslt:element name="{name($first1)}"
                                         namespace="{namespace-uri($first1)}">
                              <xslt:copy-of select="$first1/namespace::*" />
                              <xslt:copy-of select="$first2/namespace::*" />
                              <xslt:copy-of select="$first1/@*" />
                              <xslt:call-template name="m:merge">
                                 <xslt:with-param name="nodes1"
                                       select="$first1/node()" />
                                 <xslt:with-param name="nodes2"
                                       select="$nodes2[position()=$pos]/node()" />
                              </xslt:call-template>
                           </xslt:element>
                        </xslt:when>
                        <!-- Other: copy -->
                        <xslt:otherwise>
                           <xslt:copy-of select="$first1" />
                        </xslt:otherwise>
                     </xslt:choose>

                     <!-- Merge $rest1 and rest of $nodes2 -->
                     <xslt:call-template name="m:merge">
                        <xslt:with-param name="nodes1" select="$rest1" />
                        <xslt:with-param name="nodes2"
                              select="$nodes2[position() &gt; $pos]" />
                     </xslt:call-template>
                  </xslt:when>

                  <!-- $first1 is a text node and replace mode was
                       activated -->
                  <xslt:when test="$type1='text' and $replace">
                     <xslt:call-template name="m:merge">
                        <xslt:with-param name="nodes1" select="$rest1" />
                        <xslt:with-param name="nodes2" select="$nodes2" />
                     </xslt:call-template>
                  </xslt:when>

                  <!-- else: $first1 is not in $rest2 or
                       $first1 is an empty text node -->
                  <xslt:otherwise>
                     <xslt:copy-of select="$first1" />
                     <xslt:call-template name="m:merge">
                        <xslt:with-param name="nodes1" select="$rest1" />
                        <xslt:with-param name="nodes2" select="$nodes2" />
                     </xslt:call-template>
                  </xslt:otherwise>
               </xslt:choose>
            </xslt:when>

            <!-- else: $first1 = $first2 -->
            <xslt:otherwise>
               <xslt:choose>
                  <!-- Elements: merge -->
                  <xslt:when test="$type1='element'">
                     <xslt:element name="{name($first1)}"
                                   namespace="{namespace-uri($first1)}">
                        <xslt:copy-of select="$first1/namespace::*" />
                        <xslt:copy-of select="$first2/namespace::*" />
                        <xslt:copy-of select="$first1/@*" />
                        <xslt:call-template name="m:merge">
                           <xslt:with-param name="nodes1"
                                            select="$first1/node()" />
                           <xslt:with-param name="nodes2"
                                            select="$first2/node()" />
                        </xslt:call-template>
                     </xslt:element>
                  </xslt:when>
                  <!-- Other: copy -->
                  <xslt:otherwise>
                     <xslt:copy-of select="$first1" />
                  </xslt:otherwise>
               </xslt:choose>

               <!-- Merge $rest1 and $rest2 -->
               <xslt:call-template name="m:merge">
                  <xslt:with-param name="nodes1" select="$rest1" />
                  <xslt:with-param name="nodes2" select="$rest2" />
               </xslt:call-template>
            </xslt:otherwise>
         </xslt:choose>
      </xslt:otherwise>
   </xslt:choose>
</xslt:template>


<!-- Comparing single nodes:
     if $node1 and $node2 are equivalent then the template creates a
     text node "=" otherwise a text node "!" -->
<xslt:template name="m:compare-nodes">
   <xslt:param name="node1" />
   <xslt:param name="node2" />
   <xslt:variable name="type1">
      <xslt:apply-templates mode="m:detect-type" select="$node1" />
   </xslt:variable>
   <xslt:variable name="type2">
      <xslt:apply-templates mode="m:detect-type" select="$node2" />
   </xslt:variable>

   <xslt:choose>
      <!-- Are $node1 and $node2 element nodes with the same name? -->
      <xslt:when test="$type1='element' and $type2='element' and
                       local-name($node1)=local-name($node2) and
                       namespace-uri($node1)=namespace-uri($node2) and
                       name($node1)!=$dontmerge and name($node2)!=$dontmerge">
         <!-- Comparing the attributes -->
         <xslt:variable name="diff-att">
            <!-- same number ... -->
            <xslt:if test="count($node1/@*)!=count($node2/@*)">.</xslt:if>
            <!-- ... and same name/content -->
            <xslt:for-each select="$node1/@*">
               <xslt:if test="not($node2/@*
                        [local-name()=local-name(current()) and
                         namespace-uri()=namespace-uri(current()) and
                         .=current()])">.</xslt:if>
            </xslt:for-each>
         </xslt:variable>
         <xslt:choose>
            <xslt:when test="string-length($diff-att)!=0">!</xslt:when>
            <xslt:otherwise>=</xslt:otherwise>
         </xslt:choose>
      </xslt:when>

      <!-- Other nodes: test for the same type and content -->
      <xslt:when test="$type1!='element' and $type1=$type2 and
                       name($node1)=name($node2) and
                       ($node1=$node2 or
                          ($normalize='yes' and
                           normalize-space($node1)=
                           normalize-space($node2)))">=</xslt:when>

      <!-- Otherwise: different node types or different name/content -->
      <xslt:otherwise>!</xslt:otherwise>
   </xslt:choose>
</xslt:template>


<!-- Type detection, thanks to M. H. Kay -->
<xslt:template match="*" mode="m:detect-type">element</xslt:template>
<xslt:template match="text()" mode="m:detect-type">text</xslt:template>
<xslt:template match="comment()" mode="m:detect-type">comment</xslt:template>
<xslt:template match="processing-instruction()" mode="m:detect-type">pi</xslt:template>

</xslt:transform>


================================================
FILE: src/assets/semver2.sh
================================================
#!/bin/sh

# POSIX SH portable semver 2.0 comparition tool.

# This bash script compares pre-releases alphabetically as well (number < lowerCaseLetter < upperCaseLetter)
#
# returns 1 when A greater than B
# returns 0 when A equals B
# returns -1 when A lower than B
#
# Usage
# chmod +x semver.sh
# ./semver.sh 1.0.0-rc.0.a+metadata v1.0.0-rc.0+metadata
# --> 1
#

# This software was built with the help of the following sources:
# https://stackoverflow.com/a/58067270
# https://www.unix.com/man-page/posix/1posix/cut/
# https://stackoverflow.com/questions/51052475/how-to-iterate-over-the-characters-of-a-string-in-a-posix-shell-script

set -eu

debug() {
  if [ "$debug" = "debug" ]; then printf "DEBUG: %s$1 \n"; fi
}

# params char
# returns Integer
ord() {
  printf '%d' "'$1"
}


isNumber() {
  string=$1
  char=""
  while true; do
    substract="${string#?}"    # All but the first character of the string
    char="${string%"$substract"}"    # Remove $rest, and you're left with the first character
    string="$substract"
    # no more chars to compare then success
    if [ -z "$char" ]; then
      printf "true"
      return 1
    fi
    # break if some of the chars is not a number
    if [ "$(ord "$char")" -lt 48 ] || [ "$(ord "$char")" -gt 57 ]; then
      printf "false"
      return 0
    fi
  done
}

# params string {String}, Index {Number}
# returns char
getChar() {
  string=$1
  index=$2
  cursor=-1
  char=""
  while [ "$cursor" != "$index" ]; do
    substract="${string#?}"    # All but the first character of the string
    char="${string%"$substract"}"    # Remove $rest, and you're left with the first character
    string="$substract"
    cursor=$((cursor + 1))
  done
  printf "%s$char"
}

outcome() {
  result=$1
  printf "%s$result\n"
}


compareNumber() {
  if [ -z "$1" ] && [ -z "$2" ]; then
    printf "%s" "0"
    return
  fi

  [ $(($2 - $1)) -gt 0 ] && printf "%s" "-1"
  [ $(($2 - $1)) -lt 0 ] && printf "1"
  [ $(($2 - $1)) = 0 ] && printf "0"
}

compareString() {
  result=false
  index=0
  while true
  do
    a=$(getChar "$1" $index)
    b=$(getChar "$2" $index)

    if [ -z "$a" ] && [ -z "$b" ]
    then
      printf "0"
      return
    fi

    ord_a=$(ord "$a")
    ord_b=$(ord "$b")
  
    if [ "$(compareNumber "$ord_a" "$ord_b")" != "0" ]; then
      printf "%s" "$(compareNumber "$ord_a" "$ord_b")"
      return
    fi

    index=$((index + 1))
  done
}

includesString() {
  string="$1"
  substring="$2"
  if [ "${string#*$substring}" != "$string" ]
  then
    printf "1"
    return 1    # $substring is in $string
  fi
  printf "0"
  return 0    # $substring is not in $string
}

removeLeadingV() {
  printf "%s${1#v}"
}

semver_compare() {
  firstParam=$1 #1.2.4-alpha.beta+METADATA
  secondParam=$2 #1.2.4-alpha.beta.2+METADATA
  debug=${3:-1}
  verbose=${4:-1}

  [ "$verbose" = "verbose" ] && set -x

  version_a=$(printf %s "$firstParam" | cut -d'+' -f 1)
  version_a=$(removeLeadingV "$version_a")
  version_b=$(printf %s "$secondParam" | cut -d'+' -f 1)
  version_b=$(removeLeadingV "$version_b")

  a_major=$(printf %s "$version_a" | cut -d'.' -f 1)
  a_minor=$(printf %s "$version_a" | cut -d'.' -f 2)
  a_patch=$(printf %s "$version_a" | cut -d'.' -f 3 | cut -d'-' -f 1)
  a_pre=""
  if [ "$(includesString "$version_a" -)" = 1 ]; then
    a_pre=$(printf %s"${version_a#$a_major.$a_minor.$a_patch-}")
  fi

  b_major=$(printf %s "$version_b" | cut -d'.' -f 1)
  b_minor=$(printf %s "$version_b" | cut -d'.' -f 2)
  b_patch=$(printf %s "$version_b" | cut -d'.' -f 3 | cut -d'-' -f 1)
  b_pre=""
  if [ "$(includesString "$version_b" -)" = 1 ]; then
    b_pre=$(printf %s"${version_b#$b_major.$b_minor.$b_patch-}")
  fi

  unit_types="MAJOR MINOR PATCH"
  a_normalized="$a_major $a_minor $a_patch"
  b_normalized="$b_major $b_minor $b_patch"

  debug "Detected: $a_major $a_minor $a_patch identifiers: $a_pre"
  debug "Detected: $b_major $b_minor $b_patch identifiers: $b_pre"
  
  #####
  #
  # Find difference between Major Minor or Patch
  #

  cursor=1
  while [ "$cursor" -lt 4 ]
  do
    a=$(printf %s "$a_normalized" | cut -d' ' -f $cursor)
    b=$(printf %s "$b_normalized" | cut -d' ' -f $cursor)
    if [ "$a" != "$b" ]
    then
      debug "$(printf %s "$unit_types" | cut -d' ' -f $cursor) is different"
      outcome "$(compareNumber "$a" "$b")"
      return
    fi;
    debug "$(printf "%s" "$unit_types" | cut -d' ' -f $cursor) are equal"
    cursor=$((cursor + 1))
  done

  #####
  #
  # Find difference between pre release identifiers
  #

  if [ -z "$a_pre" ] && [ -z "$b_pre" ]; then
    debug "Because both are equals"
    outcome "0"
    return
  fi

  # Spec 11.3 a pre-release version has lower precedence than a normal version:
  # Example: 1.0.0-alpha < 1.0.0.

  if [ -z "$a_pre" ]; then
    debug "Because a pre-release version has lower precedence than a normal version"
    outcome "1"
    return
  fi

  if [ -z "$b_pre" ]; then
    debug "Because a pre-release version has lower precedence than a normal version"
    outcome "-1"
    return
  fi


  isSingleIdentifier() {
    substract="${2#?}"
    if [ "${1%"$2"}" = "" ]; then
      printf "true"
      return 1;
    fi
    return 0
  }

  cursor=1
  while [ $cursor -lt 4 ]
  do
    a=$(printf %s "$a_pre" | cut -d'.' -f $cursor)
    b=$(printf %s "$b_pre" | cut -d'.' -f $cursor)
    
    debug "Comparing identifier $a with $b"

    # Exit when there is nothing else to compare.
    # Most likely because they are equals
    if [ -z "$a" ] && [ -z "$b" ]
    then
      debug "are equals"
      outcome "0"
      return
    fi;

    # Spec #11 https://semver.org/#spec-item-11
    # Precedence for two pre-release versions with the same major, minor, and patch version
    # MUST be determined by comparing each dot separated identifier from left to right until a difference is found

    # Spec 11.4.4: A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.
    if [ -n "$a" ] && [ -z "$b" ]; then
      # When A is larger than B
      debug "Because A has more pre-identifiers"
      outcome "1"
      return
    fi
      
    # When A is shorter than B
    if [ -z "$a" ] && [ -n "$b" ]; then
      debug "Because B has more pre-identifiers"
      outcome "-1"
      return
    fi

    # Spec #11.4.1
    # Identifiers consisting of only digits are compared numerically.
    if [ "$(isNumber "$a")" = "true" ] || [ "$(isNumber "$b")" = "true" ]; then
      
      # if both identifiers are numbers, then compare and proceed
      if [ "$(isNumber "$a")" = "true" ] && [ "$(isNumber "$b")" = "true" ]; then
        if [ "$(compareNumber "$a" "$b")" != "0" ]; then
          debug "Number is not equal $(compareNumber "$a" "$b")"
          outcome "$(compareNumber "$a" "$b")"
          return
        fi
      fi

      # Spec 11.4.3
      if [ "$(isNumber "$a")" = "false" ]; then
        debug "Because Numeric identifiers always have lower precedence than non-numeric identifiers."
        outcome "1"
        return
      fi

      if [ "$(isNumber "$b")" = "false" ]; then
        debug "Because Numeric identifiers always have lower precedence than non-numeric identifiers."
        outcome "-1"
        return
      fi
    else
      # Spec 11.4.2
      # Identifiers with letters or hyphens are compared lexically in ASCII sort order.
      if [ "$(compareString "$a" "$b")" != "0" ]; then
        debug "cardinal is not equal $(compareString a b)"
        outcome "$(compareString "$a" "$b")"
        return
      fi
    fi

    # Edge case when there is single identifier exaple: x.y.z-beta
    if [ "$cursor" = 1 ]; then
      
      # When both versions are single return equals
      if [ -n "$(isSingleIdentifier "$b_pre" "$b")" ] && [ -n "$(isSingleIdentifier "$a_pre" "$a")" ]; then
        debug "Because both have single identifier"
        outcome "0"
        return
      fi
      
      # Return greater when has more identifiers
      # Spec 11.4.4: A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.
      
      # When A is larger than B
      if [ -n "$(isSingleIdentifier "$b_pre" "$b")" ] && [ -z "$(isSingleIdentifier "$a_pre" "$a")" ]; then
        debug "Because of single identifier, A has more pre-identifiers"
        outcome "1"
        return
      fi
      
      # When A is shorter than B
      if [ -z "$(isSingleIdentifier "$b_pre" "$b")" ] && [ -n "$(isSingleIdentifier "$a_pre" "$a")" ]; then
        debug "Because of single identifier, B has more pre-identifiers"
        outcome "-1"
        return
      fi
    fi
  
    # Proceed to the next identifier because previous comparition was equal.
    cursor=$((cursor + 1))
  done
}

printf "%s$(semver_compare "$@")\n"


================================================
FILE: tags.csv
================================================
Repository,Tag,Base Image,Aliases,Dockerfile
vromero/activemq-artemis,1.0.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:1.0-latest,Dockerfile
vromero/activemq-artemis,1.0.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:1.0-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,1.1.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:1.1-latest,Dockerfile
vromero/activemq-artemis,1.1.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:1.1-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,1.2.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:1.2-latest,Dockerfile
vromero/activemq-artemis,1.2.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:1.2-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,1.3.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:1.3-latest,Dockerfile
vromero/activemq-artemis,1.3.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:1.3-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,1.4.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:1.4-latest,Dockerfile
vromero/activemq-artemis,1.4.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:1.4-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,1.5.0,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,1.5.0-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,1.5.1,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,1.5.1-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,1.5.2,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,1.5.2-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,1.5.3,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,1.5.3-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,1.5.4,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,1.5.4-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,1.5.5,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,1.5.5-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,1.5.6,openjdk:8u232-jre-stretch,vromero/activemq-artemis:1.5-latest vromero/activemq-artemis:1-latest,Dockerfile
vromero/activemq-artemis,1.5.6-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:1.5-alpine-latest vromero/activemq-artemis:1-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.0.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.0-latest,Dockerfile
vromero/activemq-artemis,2.0.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.0-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.1.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.1-latest,Dockerfile
vromero/activemq-artemis,2.1.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.1-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.2.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.2-latest,Dockerfile
vromero/activemq-artemis,2.2.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.2-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.3.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.3-latest,Dockerfile
vromero/activemq-artemis,2.3.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.3-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.4.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.4-latest,Dockerfile
vromero/activemq-artemis,2.4.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.4-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.5.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.5-latest,Dockerfile
vromero/activemq-artemis,2.5.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.5-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.6.0,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,2.6.0-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,2.6.1,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,2.6.1-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,2.6.2,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,2.6.2-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,2.6.3,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,2.6.3-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,2.6.4,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.6-latest,Dockerfile
vromero/activemq-artemis,2.6.4-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.6-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.7.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.7-latest,Dockerfile
vromero/activemq-artemis,2.7.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.7-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.8.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.8-latest,Dockerfile
vromero/activemq-artemis,2.8.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.8-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.9.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.9-latest,Dockerfile
vromero/activemq-artemis,2.9.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.9-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.10.0,openjdk:8u232-jre-stretch,,Dockerfile
vromero/activemq-artemis,2.10.0-alpine,openjdk:8u212-jre-alpine3.9,,Dockerfile.alpine
vromero/activemq-artemis,2.10.1,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.10-latest,Dockerfile
vromero/activemq-artemis,2.10.1-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.10-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.11.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.11-latest,Dockerfile
vromero/activemq-artemis,2.11.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.11-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.12.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.12-latest,Dockerfile
vromero/activemq-artemis,2.12.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.12-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.13.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.13-latest,Dockerfile
vromero/activemq-artemis,2.13.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.13-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.14.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.14-latest,Dockerfile
vromero/activemq-artemis,2.14.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.14-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.15.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.15-latest,Dockerfile
vromero/activemq-artemis,2.15.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.15-alpine-latest,Dockerfile.alpine
vromero/activemq-artemis,2.16.0,openjdk:8u232-jre-stretch,vromero/activemq-artemis:2.16-latest vromero/activemq-artemis:2-latest vromero/activemq-artemis:latest,Dockerfile
vromero/activemq-artemis,2.16.0-alpine,openjdk:8u212-jre-alpine3.9,vromero/activemq-artemis:2.16-alpine-latest vromero/activemq-artemis:2-alpine-latest vromero/activemq-artemis:alpine-latest,Dockerfile.alpine


================================================
FILE: test/assets/1.x.x/etc-override/broker-00.xml
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
  <core xmlns="urn:activemq:core">
      <security-enabled>false</security-enabled>
   </core>
</configuration>


================================================
FILE: test/assets/1.x.x/etc-override/entrypoint-00.sh
================================================
#!/bin/sh
touch /var/lib/artemis/etc/created_by_entrypoint-00

================================================
FILE: test/assets/2.x.x/etc-override/broker-00.xml
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<configuration xmlns="urn:activemq" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
   <core xmlns="urn:activemq:core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:activemq:core ">
      <security-enabled>false</security-enabled>
   </core>
</configuration>


================================================
FILE: test/assets/2.x.x/etc-override/entrypoint-00.sh
================================================
#!/bin/sh
touch /var/lib/artemis/etc/created_by_entrypoint-00

================================================
FILE: test/assets/etc-override/jmx-exporter-config.yaml
================================================
---
lowercaseOutputName: true
lowercaseOutputLabelNames: true
rules:
  - pattern: "^org.apache.activemq.artemis<broker=\"([^\"]*)\"><>([^:]*):\\s(.*)"
    attrNameSnakeCase: true
    name: just_for_test_$2
    type: COUNTER


================================================
FILE: test/assets/goss.yaml
================================================

{{if (.Vars.flags.testmerge) }}
command:
  xmlstarlet sel -N activemq="urn:activemq" -N core="urn:activemq:core" -t -v "activemq:configuration/core:core/core:security-enabled" /var/lib/artemis/etc/broker.xml:
    exit-status: 0
    stdout:
    - false
    stderr: []
    timeout: 1000
{{end}}

command:
  ps -ef|grep -v grep|grep java:
    exit-status: 0
    stdout:
{{if getEnv "BROKER_CONFIG_GLOBAL_MAX_SIZE" }}
    - "-Dbrokerconfig.globalMaxSize={{ .Env.BROKER_CONFIG_GLOBAL_MAX_SIZE }}"
{{end}}
{{if getEnv "JAVA_OPTS" }}
    - {{ .Env.JAVA_OPTS }}
{{end}}
    stderr: []
    timeout: 1000

port:
  tcp:8161:
    listening: true
{{if getEnv "ENABLE_JMX_EXPORTER" }}
  tcp:9404:
    listening: true
{{end}}

{{if and (.Env.ACTIVEMQ_ARTEMIS_VERSION | regexMatch "(2\\.[3-9]\\.[0-9]|2\\.\\d{2}\\.[0-9]|[3-9]\\d*\\.\\d+\\.[0-9])") (getEnv "ARTEMIS_USERNAME") }}
http:
  http://127.0.0.1:8161/console:
    status: 200
  http://127.0.0.1:8161/console/jolokia:
    status: 200
    username: "{{ .Env.ARTEMIS_USERNAME }}"
    password: "{{ .Env.ARTEMIS_PASSWORD }}"
{{end}}

user:
  artemis:
    exists: true
    uid: 1000
    groups:
      - artemis

group:
  artemis:
    exists: true
    gid: 1000

process:
  java:
    running: true

file:
  /opt/apache-artemis:
    exists: true
    owner: root
    group: root
    filetype: symlink
    linked-to: /opt/apache-artemis-{{ .Env.ACTIVEMQ_ARTEMIS_VERSION }}
  
  /opt/apache-artemis-{{ .Env.ACTIVEMQ_ARTEMIS_VERSION }}:
    exists: true
    owner: root
    group: root
    filetype: directory

  /var/lib/artemis:
    exists: true
    owner: artemis
    group: artemis
    filetype: directory
  
  /var/lib/artemis/data:
    exists: true
    owner: artemis
    group: artemis
    filetype: directory

  /var/lib/artemis/etc/broker.xml:
    exists: true
    owner: artemis
    group: artemis
    filetype: file
    contains:
{{ if (.Env.ACTIVEMQ_ARTEMIS_VERSION | regexMatch "(1\\.[^0-2]\\.[0-9]+|2\\.[0-9]+\\.[0-9]+)") }}
      - <name>{{.Vars.hostname}}</name>
  {{if getEnv "DISABLE_SECURITY" }}
      - <security-enabled>false</security-enabled>
  {{end}}
{{ end }}
{{ if (.Env.ACTIVEMQ_ARTEMIS_VERSION | regexMatch "(2\\.[3-9]\\.\\d+|2\\.\\d{2}\\.\\d+)") }}
  {{if getEnv "CRITICAL_ANALYZER" }}
      - <critical-analyzer>{{.Env.CRITICAL_ANALYZER }}</critical-analyzer>
  {{end}}
  {{if getEnv "CRITICAL_ANALYZER_TIMEOUT" }}
      - <critical-analyzer-timeout>{{.Env.CRITICAL_ANALYZER_TIMEOUT }}</critical-analyzer-timeout>
  {{end}}
  {{if getEnv "CRITICAL_ANALYZER_CHECK_PERIOD" }}
      - <critical-analyzer-check-period>{{.Env.CRITICAL_ANALYZER_CHECK_PERIOD }}</critical-analyzer-check-period>
  {{end}}
  {{if getEnv "CRITICAL_ANALYZER_POLICY" }}
      - <critical-analyzer-policy>{{.Env.CRITICAL_ANALYZER_POLICY }}</critical-analyzer-policy>
  {{end}}
{{ end }}



  /var/lib/artemis/etc/artemis-users.properties:
    exists: true
    owner: artemis
    group: artemis
    filetype: file

  /var/lib/artemis/etc/artemis-roles.properties:
    exists: true
    owner: artemis
    group: artemis
    filetype: file
  
{{ if and (.Env.ACTIVEMQ_ARTEMIS_VERSION | regexMatch "(1.5.[^012]|[^1]\\.\\d+\\.\\d+)") (getEnv "ARTEMIS_PERF_JOURNAL" "AUTO" | regexMatch "AUTO") }}
  /var/lib/artemis/data/.perf-journal-completed:
    exists: true
    owner: artemis
    group: artemis
    filetype: file
{{ end }}

  /var/lib/artemis/etc/artemis.profile:
    exists: true
    owner: artemis
    group: artemis
    filetype: file
    contains:
      - "-Djava.net.preferIPv4Addresses=true"
      - "-XX:+UnlockExperimentalVMOptions"
      - "-XX:+UseCGroupMemoryLimitForHeap"
      - "-XX:MaxRAMFraction=2"
{{if getEnv "JAVA_OPTS" }}
      - "-Djavax.net.ssl.keyStore=/var/lib/artemis/etc/keystore.jks"
      - "-Djavax.net.ssl.keyStorePassword=changeit"
{{end}}
{{if getEnv "ENABLE_JMX_EXPORTER" }}
      - "jmx_prometheus_javaagent.jar=9404"
{{else}}
      - "!jmx_prometheus_javaagent.jar"  
{{end}} 
      - "$BROKER_CONFIGS"
{{ if or (getEnv "ARTEMIS_MIN_MEMORY") (getEnv "ARTEMIS_MAX_MEMORY") (getEnv "ENABLE_JMX") }}
  {{if getEnv "ARTEMIS_MIN_MEMORY" }}
      - "-Xms{{ .Env.ARTEMIS_MIN_MEMORY }}"
  {{else}}
      - "!-Xms"  
  {{end}}
  {{if getEnv "ARTEMIS_MAX_MEMORY" }}
      - "-Xmx{{ .Env.ARTEMIS_MAX_MEMORY }}"
  {{ else }}
      - "!-Xmx"
  {{end}}
  {{if getEnv "ENABLE_JMX" }}
      - "-Dcom.sun.management.jmxremote=true"
      {{ if getEnv "JMX_PORT" }}
      - "-Dcom.sun.management.jmxremote.port={{ .Env.JMX_PORT }}"
      {{ end }}
      {{ if getEnv "JMX_PORT" }}
      - "-Dcom.sun.management.jmxremote.rmi.port={{ .Env.JMX_RMI_PORT }}"
      {{ end }}
      - "-Dcom.sun.management.jmxremote.ssl=false"
      - "-Dcom.sun.management.jmxremote.authenticate=false"
  {{end}}
{{end}}

{{if (.Vars.flags.testmerge) }}
  /var/lib/artemis/etc/created_by_entrypoint-00:
    exists: true
    owner: artemis
    group: artemis
{{end}}

{{if and (getEnv "ENABLE_JMX_EXPORTER") (getEnv "TEST_CUSTOM_JMX_EXPORTER_CONFIG") }}
  /opt/jmx-exporter/etc/jmx-exporter-config.yaml:
    exists: true
    owner: artemis
    group: artemis
    contains:
      - "just_for_test"
{{end}}


================================================
FILE: test/assets/goss_wait.yaml
================================================

port:
  tcp:8161:
    listening: true


================================================
FILE: test/assets/vars-etc-override.yaml
================================================

flags:
  testmerge: true

hostname: testHostName.local


================================================
FILE: test/assets/vars.yaml
================================================

flags:
  testmerge: false

hostname: testHostName.local

================================================
FILE: test/test-dockerfile.bats
================================================
#!/usr/bin/env bats

@test "docker file must pass lint" {
	cd src && docker run --rm -i hadolint/hadolint < ${DOCKER_FILE}
}


================================================
FILE: test/test-entrypoint.bats
================================================
#!/usr/bin/env bats

@test "docker-entrypoint.sh must be a valid posix script" {
  shellcheck src/assets/docker-entrypoint.sh
}


================================================
FILE: test/test-image.bats
================================================
#!/usr/bin/env bats

@test "docker container can run with no arguments" {
  	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local ${COORDINATES}
}

@test "docker container can have JSON output" {

	# Only 2.10 and later supported
  	if $(echo "${ACTIVEMQ_ARTEMIS_VERSION}" | grep -Eq "1\.[0-9]+\.[0-9]+|2\.[0-9]{1}.[0-9]+"); then
		skip
		return
	fi

	export UUID="$(uuidgen)"
	
	docker run -d --name "$UUID" -h testHostName.local -e LOG_FORMATTER=JSON ${COORDINATES}
    
	n=0; until [ "$n" -ge 5 ]
   	do
        sleep 2
       	[ "$(docker logs --tail 1 $UUID | jq -r '.hostName')" = "testhostname.local" ] && break
       	n=$((n+1))
   	done
    
	docker stop "$UUID"
   	[ $n -lt 5 ]
}

@test "docker container can set username and password" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e ARTEMIS_USERNAME=myusername -e ARTEMIS_PASSWORD=mypassword ${COORDINATES}
}

@test "docker container can set java opts" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e "JAVA_OPTS=-Djavax.net.ssl.keyStore=/var/lib/artemis/etc/keystore.jks -Djavax.net.ssl.keyStorePassword=changeit" ${COORDINATES}
}

@test "docker container can autorun performance journal tuning" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e ARTEMIS_PERF_JOURNAL=AUTO ${COORDINATES}
}

@test "docker container can skip performance journal tuning" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e ARTEMIS_PERF_JOURNAL=NEVER ${COORDINATES}
}

@test "docker container can enable JMX" {
  	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e ENABLE_JMX=true -e JMX_PORT=2222 -e JMX_RMI_PORT=3333 -e BROKER_CONFIG_GLOBAL_MAX_SIZE=9500 ${COORDINATES}
}

@test "docker container can enable JMX exporter" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e ENABLE_JMX_EXPORTER=true ${COORDINATES}
}

@test "docker container can enable JMX exporter with custom config" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e ENABLE_JMX_EXPORTER=true -e TEST_CUSTOM_JMX_EXPORTER_CONFIG=true -v $BATS_TEST_DIRNAME/assets/etc-override:/opt/jmx-exporter/etc-override ${COORDINATES}
}

@test "docker container can set critical analyzer" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e CRITICAL_ANALYZER=false -e CRITICAL_ANALYZER_TIMEOUT=123 -e CRITICAL_ANALYZER_CHECK_PERIOD=456 -e CRITICAL_ANALYZER_POLICY=LOG ${COORDINATES}
}

@test "docker container can set memory limits" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e ARTEMIS_MIN_MEMORY=1512M -e ARTEMIS_MAX_MEMORY=3048M ${COORDINATES}
}

@test "docker container can disable security" {
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -e DISABLE_SECURITY=true ${COORDINATES}
}

@test "docker container can override etc" {
  	MAYOR=$(echo "${TAG}" | cut -d "." -f 1)
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars-etc-override.yaml" dgoss run -it --rm -h testHostName.local -v $BATS_TEST_DIRNAME/assets/$MAYOR.x.x/etc-override:/var/lib/artemis/etc-override ${COORDINATES}
}

@test "docker container can replace etc" {
	# Seems like Docker plays well with the Apple's filesystem sandbox guidelines but mktemp doesn't?
	# Using mkdir instead of mktemp
	# see: https://stackoverflow.com/questions/45122459/docker-mounts-denied-the-paths-are-not-shared-from-os-x-and-are-not-known
  	TMP_DIR=$(mkdir -p tmp)
	GOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets GOSS_VARS="vars.yaml" dgoss run -it --rm -h testHostName.local -v "${TMP_DIR}:/var/lib/artemis/etc" -e RESTORE_CONFIGURATION=true ${COORDINATES}
	rm -Rf "${TMP_DIR}"
}

Download .txt
gitextract_c_rmc8jt/

├── .travis.yml
├── BUILD.md
├── LICENSE
├── Makefile
├── README.md
├── src/
│   ├── Dockerfile
│   ├── Dockerfile.alpine
│   └── assets/
│       ├── docker-entrypoint.sh
│       ├── enable-jmx.xml
│       ├── jmx-exporter-config.yaml
│       ├── merge.xslt
│       └── semver2.sh
├── tags.csv
└── test/
    ├── assets/
    │   ├── 1.x.x/
    │   │   └── etc-override/
    │   │       ├── broker-00.xml
    │   │       └── entrypoint-00.sh
    │   ├── 2.x.x/
    │   │   └── etc-override/
    │   │       ├── broker-00.xml
    │   │       └── entrypoint-00.sh
    │   ├── etc-override/
    │   │   └── jmx-exporter-config.yaml
    │   ├── goss.yaml
    │   ├── goss_wait.yaml
    │   ├── vars-etc-override.yaml
    │   └── vars.yaml
    ├── test-dockerfile.bats
    ├── test-entrypoint.bats
    └── test-image.bats
Condensed preview — 25 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (127K chars).
[
  {
    "path": ".travis.yml",
    "chars": 2535,
    "preview": "language: bash\nservices: docker\n\nenv:\n  - VERSION=1.0.0\n  - VERSION=1.0.0 VARIANT=alpine\n  - VERSION=1.1.0\n  - VERSION=1"
  },
  {
    "path": "BUILD.md",
    "chars": 1723,
    "preview": "# Building the ActiveMQ Artemis Docker Image\n\nDepending on your platform the build process may differ slightly. Support "
  },
  {
    "path": "LICENSE",
    "chars": 11359,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "Makefile",
    "chars": 1619,
    "preview": "\n.PHONY: help build test run all\n\nVERSIONS_FILE=tags.csv\n\nALL_VERSION_TAGS=$(shell awk -F \",\" 'NR>1  {print $$2}' ${VERS"
  },
  {
    "path": "README.md",
    "chars": 35438,
    "preview": "![latest 2.16.0](https://img.shields.io/badge/latest-2.16.0-blue.svg?style=flat) ![License MIT](https://img.shields.io/b"
  },
  {
    "path": "src/Dockerfile",
    "chars": 9385,
    "preview": "# ActiveMQ Artemis\n\n##########################################################\n## Build Image                           "
  },
  {
    "path": "src/Dockerfile.alpine",
    "chars": 9604,
    "preview": "# ActiveMQ Artemis\n\n##########################################################\n## Build Image                           "
  },
  {
    "path": "src/assets/docker-entrypoint.sh",
    "chars": 9057,
    "preview": "#!/bin/sh\nset -e\n\nBROKER_HOME=/var/lib/artemis\nOVERRIDE_PATH=$BROKER_HOME/etc-override\nCONFIG_PATH=$BROKER_HOME/etc\nexpo"
  },
  {
    "path": "src/assets/enable-jmx.xml",
    "chars": 304,
    "preview": "<?xml version=\"1.0\"?>\n\n<configuration xmlns=\"urn:activemq\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:sch"
  },
  {
    "path": "src/assets/jmx-exporter-config.yaml",
    "chars": 789,
    "preview": "---\nlowercaseOutputName: true\nlowercaseOutputLabelNames: true\nrules:\n  - pattern: \"^org.apache.activemq.artemis<broker=\\"
  },
  {
    "path": "src/assets/merge.xslt",
    "chars": 11880,
    "preview": "<?xml version=\"1.0\"?>\n\n<!--\n   Merging two XML files\n   Version 1.6\n   LGPL (c) Oliver Becker, 2002-07-05\n   obecker@inf"
  },
  {
    "path": "src/assets/semver2.sh",
    "chars": 8813,
    "preview": "#!/bin/sh\n\n# POSIX SH portable semver 2.0 comparition tool.\n\n# This bash script compares pre-releases alphabetically as "
  },
  {
    "path": "tags.csv",
    "chars": 7303,
    "preview": "Repository,Tag,Base Image,Aliases,Dockerfile\nvromero/activemq-artemis,1.0.0,openjdk:8u232-jre-stretch,vromero/activemq-a"
  },
  {
    "path": "test/assets/1.x.x/etc-override/broker-00.xml",
    "chars": 327,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\n<configuration xmlns=\"urn:activemq\" xmlns:xsi=\"http://www.w3.org"
  },
  {
    "path": "test/assets/1.x.x/etc-override/entrypoint-00.sh",
    "chars": 61,
    "preview": "#!/bin/sh\ntouch /var/lib/artemis/etc/created_by_entrypoint-00"
  },
  {
    "path": "test/assets/2.x.x/etc-override/broker-00.xml",
    "chars": 422,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\n<configuration xmlns=\"urn:activemq\" xmlns:xsi=\"http://www.w3.org"
  },
  {
    "path": "test/assets/2.x.x/etc-override/entrypoint-00.sh",
    "chars": 61,
    "preview": "#!/bin/sh\ntouch /var/lib/artemis/etc/created_by_entrypoint-00"
  },
  {
    "path": "test/assets/etc-override/jmx-exporter-config.yaml",
    "chars": 224,
    "preview": "---\nlowercaseOutputName: true\nlowercaseOutputLabelNames: true\nrules:\n  - pattern: \"^org.apache.activemq.artemis<broker=\\"
  },
  {
    "path": "test/assets/goss.yaml",
    "chars": 5135,
    "preview": "\n{{if (.Vars.flags.testmerge) }}\ncommand:\n  xmlstarlet sel -N activemq=\"urn:activemq\" -N core=\"urn:activemq:core\" -t -v "
  },
  {
    "path": "test/assets/goss_wait.yaml",
    "chars": 39,
    "preview": "\nport:\n  tcp:8161:\n    listening: true\n"
  },
  {
    "path": "test/assets/vars-etc-override.yaml",
    "chars": 56,
    "preview": "\nflags:\n  testmerge: true\n\nhostname: testHostName.local\n"
  },
  {
    "path": "test/assets/vars.yaml",
    "chars": 56,
    "preview": "\nflags:\n  testmerge: false\n\nhostname: testHostName.local"
  },
  {
    "path": "test/test-dockerfile.bats",
    "chars": 125,
    "preview": "#!/usr/bin/env bats\n\n@test \"docker file must pass lint\" {\n\tcd src && docker run --rm -i hadolint/hadolint < ${DOCKER_FIL"
  },
  {
    "path": "test/test-entrypoint.bats",
    "chars": 128,
    "preview": "#!/usr/bin/env bats\n\n@test \"docker-entrypoint.sh must be a valid posix script\" {\n  shellcheck src/assets/docker-entrypoi"
  },
  {
    "path": "test/test-image.bats",
    "chars": 4092,
    "preview": "#!/usr/bin/env bats\n\n@test \"docker container can run with no arguments\" {\n  \tGOSS_FILES_PATH=$BATS_TEST_DIRNAME/assets G"
  }
]

About this extraction

This page contains the full source code of the vromero/activemq-artemis-docker GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 25 files (117.7 KB), approximately 34.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!