diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..19852da --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +.git +.gradle +.idea +art +build +images +run +templates + +*.zip +gradlew.bat +template.xsd diff --git a/.gitignore b/.gitignore index 07e3019..243d98a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,10 @@ +.gradle /run/ +/build/ +/images/ +/templates/ +/art/ + +*.swp +*.txt +*.zip diff --git a/README.md b/README.md index 6eee41e..2deba4c 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,11 @@ A tool to assemble Magic: The Gathering proxies from a set of template images. T ## Building Proximity can be built using the command `gradlew shadowJar`, or by running the `shadowJar` task in your IDE. + +# Docker support +To run this tool in docker, clone the repository, then run the below command from the root of the project. +If you are on Linux, make sure the read the segment on file ownership in the [docker readme](./docker/README.md). +``` +docker-compose -f docker/docker-compose.yml up +``` +For more details on the docker setup, and how to tweek if further, please see the [docker readme](./docker/README.md). \ No newline at end of file diff --git a/art/.gitkeep b/art/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/cards.txt b/cards.txt new file mode 100644 index 0000000..4dfcc32 --- /dev/null +++ b/cards.txt @@ -0,0 +1,3 @@ +1x Peek +1x Shock +1x Murder \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..2e85693 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,14 @@ +FROM gradle:jdk16 AS compiler +WORKDIR /home/gradle + +COPY gradle build.gradle gradlew settings.gradle ./ +COPY src src +RUN gradle shadowJar + +FROM adoptopenjdk:16-jre-hotspot AS runner +WORKDIR /app + +COPY --from=compiler /home/gradle/build/**/*all.jar proximity.jar +COPY docker/entrypoint.sh entrypoint.sh + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000..d2e19cb --- /dev/null +++ b/docker/README.md @@ -0,0 +1,94 @@ +# Running the docker image via compose +To run this tool in docker, clone the repository, then, depending on platform, run the below command from the root of the project: +``` +docker-compose -f docker/docker-compose.yml up +``` +Remember that once a docker image is built, it will be reused for all subsequent runs unless a new image +is created that replaces it. To rebuild the image (if you pull new code changes, for example), append +the `--build` flag to the command, like this: +``` +docker-compose -f docker/docker-compose.yml up --build +``` + +# Tweeking docker setup +This section aims to explain the different docker settings you can tinker with, as well as motivating some of +the design choices that's been made with regards to the docker files. + +## Docker compose settings +The `docker-compose.yml` file controls what's going on once we run Proximity inside the docker container. +There are a couple of defaults set to give a smooth user experience firs time around: We +automatically mount and use the `cards.txt` file as the cardslist we'll generate, and we automatically +mount the `run/templates` folder, and use the `normal` template for card generation. Lastly, we mount +the `images` folder as output target for the Proximity process. + +### Change the cards list +The simplest solution is to just edit the content of the existing `cards.txt` file to whatever you want. +If that for some reason isn't an option, and you would like to use another file for cards, replace the path +of the file to mount as cardslist (What's left of the `:` in Volume 1. The path is relative to the +docker-compose.yml file). + +### Change the template +If you would like to use another template, the easiest solution is to place it in the `run/templates` +folder, and change `normal` in the `--template=normal` part of the run command to the name of the +new template folder (or the zip file, if you opt for using a zip). + +### Change the output folder +If you would like to change the output folder, replace the path of the mounted output folder. +(What's left of the `:` in Volume 1. The path is relative to the docker-compose.yml file). + +### Change command-line flags +If you want to add additional command line flags to pass to Proximity, the easiest is to just add them +at the end of the `command` section. A complete list of command-line flags that can be passed can be found +on the [wiki](https://github.com/Haven-King/Proximity/wiki). + +## Running without compose +If you for some reason want to run the docker image without using compose, you will need to mount the +various volumes manually, and pass the appropriate CLI flags. By default, the image is design to use `/app` + as working directory. So the most convenient is to mount your list of cards at `/app/cardslist` and +your template at `/app/templates/normal`. Then, you will also need to mount an output folder, to be +able to extract the generated cards. Proximity outputs cards in a folder called `images`, so you'll +need to mount a folder at `/app/images` to be able to extract them. + +An example command to achieve all this would be the following. This command will run Proximity with the +required mounts, and will include the `--cards` and `--template` flag. +``` +docker run \ + -v $PWD/cards.txt:/app/cardslist \ + -v $PWD/run/templates:/app/templates \ + -v $PWD/images:/app/images \ + -v $PWD/art:/app/art \ + proximity:latest \ + --cards=cardslist --template=normal +``` + +## File owners on Linus +Files generated inside a docker container is owned by whatever process is executing the docker process. On +Mac and Windows, the docker process is run by the current user process, so files generated by the docker +process is owned by the user. But on Linux, the docker process is normally run as the `root` user. This +is normally not a problem, since docker isolates its file system inside the container. Proximity however +generates files that we want to access from outside the container (the output images), and thus, we mount +a directory to gain access to those files once they are generated. But since the files were generated by +the root user on Linux, normal users can't access these files. + +For some distros of Linux, you can grant access to files generated by the docker process by adding your +user to the `docker` group (see for example [Arch's instructions](https://wiki.archlinux.org/title/Docker#Installation)). +This might not always be an option for you though: being part of the docker group easilly gives the user +priveledge access to the system via `docker run --privileged`. + +Thus, we need a way for the docker process to generate files that can be accessed by the host user. There +are a few ways you can go about it, and the most common way is to set tell docker what user id and group id +to execute the container as (i.e. the `-u` flag or `user` in compose). But setting the user can have +some odd side effects on programs running in a container, because the assigned user doesn't really +exist and thus doesn't have what a program might assume a user has (for example, a home directory). +It also isn't easy to shop those settings pre-configured in a compose file, + +Instead, we went with an approach where users may supply their user id and group id as environment +variables when executing the docker compose command. If the `GROUP_ID` and `USER_ID` env vars are +set when composer runs, those values are passed to the container. The entrypoint script will then +see these values, and run `chown -R` for those values on the generated output. + +### TL:DR +Run the following on a Linux machine if you experience problems with file ownership: +```` +GROUP_ID=$(id -g) USER_ID=$(id -u) docker-compose -f docker/docker-compose.yml up +``` diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..ed34a49 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3' +services: + proximity: + build: + context: ../ + dockerfile: ./docker/Dockerfile + environment: + USER_ID: ${USER_ID:-0} + GROUP_ID: ${GROUP_ID:-0} + TEMPLATE_NAME: ${TEMPLATE_NAME:-} + image: proximity:latest + volumes: + - ../cards.txt:/app/cardslist # Volume 1 - Mounts the default 'cards.txt' as cardslist + - ../templates:/app/templates # Volume 2 - Mounts templates from run/templates (i.e. normal and classic) + - ../images:/app/images # Volume 3 - Mounts the output folder + - ../art:/app/art # Volume 4 - Mounts local art folder + command: --cards=cardslist --template=$TEMPLATE_NAME --use_official_art=true diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 0000000..ac71c04 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,19 @@ +#!/bin/sh +set -e + +# if the first arg is an option, pass all args to proximity +# else just exec whatever was supplied +if [ -z "$1" ]; then + echo "Please either supply options for Proximity, or a command to execute" +elif [ "${1#-}" != "$1" ]; then + java -jar proximity.jar "$@" +else + exec "$@" +fi + +# if the USER_ID and GROUP_ID env vars are not 0, and the /app/images +# directory exists, chown /app/images to user USER_ID:GROUP_ID +if [ "$USER_ID" -ne "0" -a "$GROUP_ID" -ne "0" -a -d "/app/images" ]; then + echo "Running: chown -R $USER_ID:$GROUP_ID /app/images" + chown -R $USER_ID:$GROUP_ID /app/images +fi diff --git a/templates/.gitkeep b/templates/.gitkeep new file mode 100644 index 0000000..e69de29