Skip to content

Commit a3e0257

Browse files
authored
Merge pull request #207 from mendix/address-user-feedback
Address user feedback and prepare new major version release
2 parents a4d7ab3 + 3ff535a commit a3e0257

File tree

5 files changed

+100
-32
lines changed

5 files changed

+100
-32
lines changed

README.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
The Mendix Buildpack for Docker (aka docker-mendix-buildpack) is an **example project** you can use to build and run your Mendix Application in a [Docker](https://www.docker.com/) container.
66

7-
**⚠️ Warning** If your pipeline is based on Docker Buildpack V4 or an earlier version, see the [upgrading from Docker Buildpack v4](upgrading-from-v4.md) document. To use Docker Buildpack v5, some changes will be required in your build process.
7+
**⚠️ Warning** If your pipeline is based on Docker Buildpack v5 or an earlier version, see the [upgrading from Docker Buildpack v5](upgrading-from-v6.md) document. To use Docker Buildpack v6, some changes will be required in your build process.
88

99
For a Kubernetes native solution to run Mendix apps, see [Mendix for Private Cloud](https://www.mendix.com/evaluation-guide/app-lifecycle/mendix-for-private-cloud/).
1010

@@ -42,8 +42,14 @@ This project is a goto reference for the following scenarios :
4242
* Docker 20.10 (Installation [here](https://docs.docker.com/engine/installation/))
4343
* Earlier Docker versions are no longer compatible because they don't support multistage builds.
4444
To use Docker versions below 20.10, download an earlier Mendix Docker Buildpack release, such as [v2.3.2](https://github.com/mendix/docker-mendix-buildpack/releases/tag/v2.3.2)
45-
* Python 3.8
46-
* For preparing, a local installation of `curl`
45+
* Alternatively, Podman version 5 or later
46+
* Python 3, version 3.8 or later
47+
* No additional dependencies are needed
48+
* In Windows, only Python running in Windows Subsystem for Linux is supported
49+
* A UNIX-like operating system, such as Linux or macOS, or Windows Subsystem for Linux
50+
* An x86-64 (AMD64) based CPU
51+
* ARM64 CPUs are not fully supported
52+
* For running the example tests, a local installation of `curl`
4753
* For local testing, make sure you can run the [docker-compose command](https://docs.docker.com/compose/install/)
4854
* A Mendix app based on Mendix 8 or a later version
4955

@@ -52,7 +58,7 @@ This project is a goto reference for the following scenarios :
5258
### Preparation: rootfs
5359

5460
To save build time, the build pack needs a prebuilt rootfs containing the base OS and additional packages.
55-
This rootfs is based on [Red Hat Universal Base Image 8 minimal](https://developers.redhat.com/articles/ubi-faq) image.
61+
This rootfs is based on [Red Hat Universal Base Image 9 minimal](https://developers.redhat.com/articles/ubi-faq) image.
5662

5763
To build the rootfs, run the following commands
5864

@@ -83,15 +89,15 @@ docker push <app-root-fs-image-tag>
8389

8490
When building the the `rootfs-builder.dockerfile` file, you can provide the following additional arguments:
8591

86-
- **CF_BUILDPACK** is a version of CloudFoundry buildpack. Defaults to `v5.0.16`. For stable pipelines, it's recommended to use a fixed **v5.0.16** version. Other Cloud Foundry buildpacks might not work with this version of Docker Buildpack.
92+
- **CF_BUILDPACK** is a version of CloudFoundry buildpack. Defaults to `v5.0.23`. For stable pipelines, it's recommended to use a fixed **v5.0.23** version. Other Cloud Foundry buildpacks might not work with this version of Docker Buildpack.
8793
- **CF_BUILDPACK_URL** specifies the URL where the CF buildpack should be downloaded from (for example, a local mirror). Defaults to `https://github.com/mendix/cf-mendix-buildpack/releases/download/${CF_BUILDPACK}/cf-mendix-buildpack.zip`. Specifying **CF_BUILDPACK_URL** will override the version from **CF_BUILDPACK**.
8894
- **BUILDPACK_XTRACE** can be used to enable CF Buildpack [debug logging](https://github.com/mendix/cf-mendix-buildpack#logging-and-debugging). Set this variable to `true` to enable debug logging.
8995

9096
### Compile an MDA
9197

9298
If your app is a source MPK file, an MPR project directory or a compressed MDA file, it needs to be converted or compiled into a format supported by CF Buildpack - an extracted MDA file.
9399

94-
This feature is available in Docker Buildpack version v5.1.0 and later, and is intended to allow building Mendix 10 apps in custom CI/CD pipelines.
100+
This feature is available in Docker Buildpack version v6.0.0 and later, and is intended to allow building Mendix 8, 9 and 10 apps in custom CI/CD pipelines.
95101

96102
To do this, run:
97103

@@ -121,13 +127,12 @@ Before running the container, it is necessary to build the image with your appli
121127

122128
```
123129
docker build \
124-
--build-arg BUILD_PATH=<mendix-project-location> \
125130
--tag mendix/mendix-buildpack:v1.2 .
126131
```
127132

128133
For build you can provide next arguments:
129134

130-
- **BUILD_PATH** indicates where the application model is located. It is a root directory of an unzipped .MDA or .MPK file. In the latter case, this is the directory where your .MPR file is located. Must be within [build context](https://docs.docker.com/engine/reference/commandline/build/#extended-description). Defaults to `./project`.
135+
- **BUILD_PATH** indicates where the application model is located. It is a root directory of an unzipped .MDA or .MPK file. In the latter case, this is the directory where your .MPR file is located. Must be within [build context](https://docs.docker.com/engine/reference/commandline/build/#extended-description). Should not be used when using the `build.py` script. Defaults to `./project`.
131136
- **ROOTFS_IMAGE** is a type of rootfs image. Defaults to `mendix-rootfs:app` (a locally prebuilt image).
132137
- **BUILDER_ROOTFS_IMAGE** is a type of rootfs image used for downloading the Mendix app dependencies and compiling the Mendix app from source. Defaults to `mendix-rootfs:builder` (a locally prebuilt image).
133138
- **EXCLUDE_LOGFILTER** will exclude the `mendix-logfilter` binary from the resulting Docker image if set to `true`. Defaults to `true`. Excluding `mendix-logfilter` will reduce the image size and remove a component that's not commonly used; the `LOG_RATELIMIT` environment variable option will be disabled.
@@ -398,9 +403,7 @@ Contributions are welcomed:
398403

399404
### Build Details
400405

401-
This was built with the following:
402-
403-
* Docker version 20.10
406+
Docker Buildpack is tested by running a Github Actions pipeline.
404407

405408
### Versioning
406409

build.py

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,15 @@ def parse_version(version):
189189
return tuple([ int(n) for n in version.split('.') ])
190190

191191
def prepare_destination(destination_path):
192-
with os.scandir(destination_path) as entries:
193-
for entry in entries:
194-
if entry.is_dir() and not entry.is_symlink():
195-
shutil.rmtree(entry.path)
196-
else:
197-
os.remove(entry.path)
192+
if os.path.exists(destination_path):
193+
with os.scandir(destination_path) as entries:
194+
for entry in entries:
195+
if entry.is_dir() and not entry.is_symlink():
196+
shutil.rmtree(entry.path)
197+
else:
198+
os.remove(entry.path)
199+
else:
200+
os.makedirs(destination_path, 0o755)
198201
project_path = os.path.join(destination_path, 'project')
199202
os.mkdir(project_path, 0o755)
200203
shutil.copytree('scripts', os.path.join(destination_path, 'scripts'))
@@ -224,14 +227,6 @@ def prepare_mda(source_path, destination_path, artifacts_repository=None):
224227
else:
225228
raise Exception('No supported files found in source path')
226229

227-
def build_image(mda_dir):
228-
# TODO: build the full image, or just copy MDA into destination?
229-
mda_path = mda_dir.name if isinstance(mda_dir, tempfile.TemporaryDirectory) else mda_dir
230-
mda_metadata = get_metadata_value(mda_path)
231-
mx_version = mda_metadata['RuntimeVersion']
232-
java_version = mda_metadata.get('JavaVersion', 11)
233-
logging.debug("Detected Mendix {} Java {}".format(mx_version, java_version))
234-
235230
if __name__ == '__main__':
236231
parser = argparse.ArgumentParser(description='Build a Mendix app')
237232
parser.add_argument('--source', metavar='source', required=True, nargs='?', type=pathlib.Path, help='Path to source Mendix app (MDA file, MPK file, MPR directory or extracted MDA directory)')
@@ -247,4 +242,3 @@ def build_image(mda_dir):
247242
except KeyboardInterrupt:
248243
stop_processes()
249244
raise
250-
# build_image(args.destination)

mxbuild/build

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,28 @@ fi
1515

1616
cd /workdir
1717

18-
if [ -f /workdir/project ]; then
19-
JAVA_VERSION=$(cat java-version)
18+
if [ -f /workdir/project/java-version ]; then
19+
echo "Using java-version to select Java version"
20+
JAVA_VERSION=$(cat /workdir/project/java-version)
2021
elif [ -f /opt/mendix/modeler/mx ]; then
21-
JAVA_VERSION=$(/opt/mendix/modeler/mx dump-mpr --unit-type 'Settings$ProjectSettings' /workdir/project/"${MPR_FILENAME}" | \
22-
jq -r '.units[] | select(.["$Type"]=="Settings$ProjectSettings") | .["settingsParts"][] | select(.["$Type"]=="Settings$RuntimeSettings").javaVersion | if (. == null or . == "null") then "Java11" else . end')
22+
if JAVA_VERSION=$(/opt/mendix/modeler/mx show-java-version /workdir/project/"${MPR_FILENAME}"); then
23+
echo "Using mx show-java-version to select Java version"
24+
elif JAVA_VERSION=$(PROJECT_SETTINGS=`/opt/mendix/modeler/mx dump-mpr --unit-type 'Settings$ProjectSettings' /workdir/project/"${MPR_FILENAME}"` && \
25+
echo -n $PROJECT_SETTINGS | \
26+
jq -r '.units[] | select(.["$Type"]=="Settings$ProjectSettings") | .["settingsParts"][] | select(.["$Type"]=="Settings$RuntimeSettings").javaVersion | if (. == null or . == "null") then "Java11" else . end'); then
27+
echo "Using mx dump-mpr to select Java version"
28+
else
29+
echo "Unable to detect Java version using mx tool"
30+
JAVA_VERSION=11
31+
fi
2332
else
33+
echo "mx tool is not available"
2434
JAVA_VERSION=11
2535
fi
2636

2737
JAVA_VERSION=$(echo -n $JAVA_VERSION| sed s/\^Java// | head)
2838

29-
echo "Detected Java $JAVA_VERSION"
39+
echo "Using Java $JAVA_VERSION"
3040
export JDK_HOME=/etc/alternatives/java_sdk_${JAVA_VERSION}
3141

3242
$MXBUILD_COMMAND \

rootfs-builder.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ENV LANG C.UTF-8
1010
ENV LC_ALL C.UTF-8
1111

1212
# CF buildpack version
13-
ARG CF_BUILDPACK=v5.0.20
13+
ARG CF_BUILDPACK=v5.0.23
1414
# CF buildpack download URL
1515
ARG CF_BUILDPACK_URL=https://github.com/mendix/cf-mendix-buildpack/releases/download/${CF_BUILDPACK}/cf-mendix-buildpack.zip
1616

upgrading-from-v5.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Upgrading from Docker Buildpack v5
2+
3+
Docker Buildpack v6 contains a breaking change and might require some changes in your CI/CD pipeline:
4+
5+
Building Mendix projects from source (\*.mpr or \*.mpk files) is now done using a build.py script.
6+
If your CI/CD pipeline uses Docker Buildpack to build \*.mda files (compiled Mendix apps), no further changes are needed.
7+
8+
If you're upgrading from Docker Buildpack v4 (or an older version), you'll also need to follow the [upgrading from Docker Buildpack v4](upgrading-from-v4.md) instructions.
9+
10+
⚠️ If your current pipeline is failing with an _Only Ubuntu is supported_ error, your pipeline depends on CF Buildpack to build Mendix MPR files, and needs to be updated as described in this document.
11+
12+
## Using the build.py script
13+
14+
Docker Buildpack v6 no longer uses CF Buildpack to compile MPR (or MPK) files - to continue supporting newer versions of Mendix, Java and the base OS.
15+
Instead, a custom `build.py` script will:
16+
17+
1. Prepare a clean [Docker context](https://docs.docker.com/build/concepts/context/) in the path specified by `--destination`. All files required to build the app image will be copied to this destination. If the directory doesn't exist, the `build.py` script will create it; if the directory is not empty, `build.py` will delete its contents.
18+
2. Detect the file type of the source path specified by the `--source` arg (an MPK file, an MPR file, an MDA file or an unpacked MDA directory).
19+
3. If necessary (`--source` specifies project that needs to be compiled)
20+
1. Create an image containing [mxbuild](https://docs.mendix.com/refguide/mxbuild/) and its dependencies.
21+
2. Run an `mxbuild` in a container, and copy the resulting MDA contents to the destination path specified by `--destination`.
22+
4. Otherwise (`--source` specifies a path to an MDA file or unpacked MDA directory), `build.sh` will just copy the MDA contents to the destination path specified by `--destination`.
23+
24+
Once the `build.py` script runs successfully, the path specified by `--destination` will contain a Docker context and everything needed to run a `docker build` command.
25+
26+
### Updating an existing pipeline to use build.py
27+
28+
There instructions are provided as a reference, based on a typical pipeline. Your CI/CD pipeline might be different - for support with updating a custom pipeline, please check the [Mendix Support Policy](https://www.mendix.com/evaluation-guide/evaluation-learning/support/).
29+
30+
1. Verify your pipeline image or runner has Python 3.8 available, and uses a UNIX-like operating system (Linux, macOS or Windows Subsystem for Linux).
31+
2. Locate the `docker build` step in your CI/CD pipeline that builds the app image. This should be the step that builds the Mendix app, and not the rootfs or its dependencies. Any `docker build` commands that build the rootfs should not be changed.
32+
3. Before the `docker build` step, add the following lines (replacing `<path-to-source>` with the path to the project source, and `<destination-dir>` with an empty/temporary writable path):
33+
```shell
34+
./build.py --source <path-to-source> --destination <destination-dir> build-mda-dir
35+
```
36+
4. In the `docker build` step:
37+
* Remove `--build-arg BUILD_PATH` args.
38+
* Remove `-f` and `--file` args specifying a Dockerfile, if they exist.
39+
* Update the [Docker context](https://docs.docker.com/build/concepts/context/) path to the `<destination-dir>`.
40+
41+
After the update, your pipeline might look like this:
42+
43+
```shell
44+
# Preparation steps
45+
# Downloag Docker Buildpack
46+
DOCKER_BUILDPACK_VERSION=v6.0.0
47+
curl -LJ -o - https://github.com/mendix/docker-mendix-buildpack/archive/refs/tags/${DOCKER_BUILDPACK_VERSION}.tar.gz | tar --strip-components=1 -xvz
48+
# Checkout the Mendix app source
49+
git clone <mendix-app-git> mendix-app-src
50+
# Build the Mendix app from mendix-app-src to a temporary location
51+
./build.py --source mendix-app-src --destination /tmp/docker-buildpack-context build-mda-dir
52+
# Prepare and push the Docker image, using /tmp/docker-buildpack-context as the Docker context
53+
docker build --tag example.com/mendix-app:latest /tmp/docker-buildpack-context
54+
docker push example.com/mendix-app:latest
55+
# Follow-up steps
56+
```
57+
58+
# Other changes
59+
60+
Docker Buildpack v6 switched from `ubi8` to `ubi9` images ([Red Hat Universal Base Images](https://developers.redhat.com/articles/ubi-faq) whenever possible.
61+
Building Mendix 8 and 9 apps still uses `ubi8`, as those versions depend on an older version of Mono that doesn't work in newer operating systems.

0 commit comments

Comments
 (0)