mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-02-17 23:16:24 +00:00
Compare commits
71 Commits
1.4.1
...
1.8.0-mult
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bacaa11d8 | ||
|
|
4fe55b5a28 | ||
|
|
bd503f224d | ||
|
|
b5c91647ca | ||
|
|
c359a0f2ac | ||
|
|
c7c4c7497a | ||
|
|
e442baab31 | ||
|
|
8101c8b51c | ||
|
|
49d9f4a89d | ||
|
|
aebe35c9d4 | ||
|
|
a26361c79f | ||
|
|
eba1ef6ab9 | ||
|
|
a486458a08 | ||
|
|
82b8401414 | ||
|
|
8b6ee91ec1 | ||
|
|
06cffd9e15 | ||
|
|
beaccbcf3b | ||
|
|
21ee5e2401 | ||
|
|
6462e1580c | ||
|
|
8b5552bb62 | ||
|
|
747c188824 | ||
|
|
692087dd25 | ||
|
|
6fe13e8654 | ||
|
|
3b2b98b9fe | ||
|
|
796f2fe14a | ||
|
|
4fef391b64 | ||
|
|
83f6cebd0b | ||
|
|
90183ae823 | ||
|
|
3c9df03584 | ||
|
|
367c6cfd92 | ||
|
|
5e75410e7c | ||
|
|
38028f7d0c | ||
|
|
3ca514f2b2 | ||
|
|
a07ae685e2 | ||
|
|
c07f899870 | ||
|
|
092b530537 | ||
|
|
cf691499a1 | ||
|
|
0bb9cccdc6 | ||
|
|
4cb12f6cae | ||
|
|
ecbdeb2096 | ||
|
|
9a7a532f7b | ||
|
|
825833c859 | ||
|
|
c4c3613874 | ||
|
|
e527fd9551 | ||
|
|
047a477f7b | ||
|
|
78cb05adda | ||
|
|
8493252645 | ||
|
|
aa42633ab2 | ||
|
|
9ec336283f | ||
|
|
bbdb2c9b36 | ||
|
|
48e09f42fc | ||
|
|
ec7d182d38 | ||
|
|
9c7c95cf4f | ||
|
|
e32ffd1819 | ||
|
|
095c6ad099 | ||
|
|
14342c9632 | ||
|
|
f6df4d6694 | ||
|
|
0406e89c2a | ||
|
|
5ef21e1ddf | ||
|
|
414d5bd8ac | ||
|
|
15ccf03b28 | ||
|
|
828a48998f | ||
|
|
4b590e03ff | ||
|
|
0db8780ad9 | ||
|
|
5b744176df | ||
|
|
20b15e0330 | ||
|
|
818539e3de | ||
|
|
f48741f65c | ||
|
|
e9e5af849f | ||
|
|
22d68f5c7c | ||
|
|
690598da60 |
@@ -1,5 +1,6 @@
|
||||
data
|
||||
testdata
|
||||
examples
|
||||
k8s-examples
|
||||
.idea
|
||||
.git
|
||||
.git
|
||||
|
||||
25
.github/workflows/build-multiarch.yml
vendored
Normal file
25
.github/workflows/build-multiarch.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Build and publish multiarch
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- multiarch
|
||||
tags:
|
||||
- "[0-9]+.[0-9]+.[0-9]+-multiarch"
|
||||
|
||||
jobs:
|
||||
docker-buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2.2.0
|
||||
- name: Get branch name
|
||||
uses: nelonoel/branch-name@v1
|
||||
- name: Docker Buildx
|
||||
uses: ilteoood/docker_buildx@1.0.4
|
||||
with:
|
||||
publish: true
|
||||
imageName: itzg/minecraft-server
|
||||
tag: ${{ env.BRANCH_NAME }}
|
||||
dockerHubUser: ${{ secrets.DOCKER_USER }}
|
||||
dockerHubPassword: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
12
.github/workflows/main.yml
vendored
12
.github/workflows/main.yml
vendored
@@ -16,7 +16,18 @@ on:
|
||||
- "[0-9]+.[0-9]+.[0-9]+-adopt13"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
tests/test.sh
|
||||
build:
|
||||
needs:
|
||||
- test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -32,4 +43,5 @@ jobs:
|
||||
tag_with_sha: false
|
||||
cache_froms: itzg/minecraft-server:latest
|
||||
add_git_labels: true
|
||||
labels: org.opencontainers.image.url=https://github.com/itzg/docker-minecraft-server,org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server
|
||||
push: true
|
||||
|
||||
11
.github/workflows/pr.yml
vendored
11
.github/workflows/pr.yml
vendored
@@ -5,15 +5,12 @@ on:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build Docker image
|
||||
uses: docker/build-push-action@v1.1.0
|
||||
with:
|
||||
tag_with_sha: true
|
||||
cache_froms: itzg/minecraft-server:latest
|
||||
push: false
|
||||
- name: Run tests
|
||||
run: |
|
||||
tests/test.sh
|
||||
|
||||
11
BUILDING.md
Normal file
11
BUILDING.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Ensure buildx/BuildKit support is enabled and run:
|
||||
|
||||
```shell script
|
||||
docker buildx build --platform=linux/arm64 --platform=linux/arm/v7 --platform=linux/amd64 --tag itzg/minecraft-server:multiarch --push .
|
||||
```
|
||||
|
||||
To build for local testing, use:
|
||||
|
||||
```shell script
|
||||
docker buildx build --platform=linux/amd64 --tag mc-multiarch --load .
|
||||
```
|
||||
@@ -3,7 +3,7 @@
|
||||
Adding a new server `TYPE` can vary due to the complexity of obtaining and configuring each type; however, the addition of any server type includes at least the following steps:
|
||||
|
||||
1. Copy an existing "start-deploy*" script, such as [start-deployMohist](start-deployMohist) and rename it accordingly making sure to retain the "start-deploy" prefix
|
||||
2. Modify the type-specific behavior between the "start-utils" preamble and the hand-off to `start-finalSetup01World` at the end of the script
|
||||
2. Modify the type-specific behavior between the "start-utils" preamble and the hand-off to `start-finalSetupWorld` at the end of the script
|
||||
3. Develop and test the changes using the [iterative process described below](#iterative-script-development)
|
||||
4. Add a case-entry to the `case "${TYPE^^}"` in [start-configuration](start-configuration)
|
||||
5. Add a section to the [README](README.md). It is recommended to copy-modify an existing section to retain a similar wording and level of detail
|
||||
@@ -70,5 +70,5 @@ The multiarch images are built and published by [a Github action](https://github
|
||||
The following git command can be used to provide the bulk of release notes content:
|
||||
|
||||
```shell script
|
||||
git log --invert-grep --grep "^ci:" --grep "^misc:" --pretty="- %s" 1.1.0..1.2.0
|
||||
git log --invert-grep --grep "^ci:" --grep "^misc:" --grep "^docs:" --pretty="- %s" 1.1.0..1.2.0
|
||||
```
|
||||
|
||||
53
Dockerfile
53
Dockerfile
@@ -1,29 +1,27 @@
|
||||
FROM openjdk:8u212-jre-alpine
|
||||
FROM ubuntu:18.04
|
||||
|
||||
LABEL maintainer "itzg"
|
||||
LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>"
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
openssl \
|
||||
imagemagick \
|
||||
lsof \
|
||||
su-exec \
|
||||
shadow \
|
||||
bash \
|
||||
curl iputils wget \
|
||||
git \
|
||||
jq \
|
||||
mysql-client \
|
||||
tzdata \
|
||||
rsync \
|
||||
nano \
|
||||
sudo \
|
||||
knock \
|
||||
ttf-dejavu
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive \
|
||||
apt-get install -y \
|
||||
openjdk-8-jre-headless \
|
||||
imagemagick \
|
||||
gosu \
|
||||
curl wget \
|
||||
jq \
|
||||
dos2unix \
|
||||
mysql-client \
|
||||
tzdata \
|
||||
rsync \
|
||||
nano \
|
||||
unzip \
|
||||
knockd \
|
||||
ttf-dejavu \
|
||||
&& apt-get clean
|
||||
|
||||
RUN addgroup -g 1000 minecraft \
|
||||
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
|
||||
&& mkdir -m 777 /data \
|
||||
&& chown minecraft:minecraft /data /home/minecraft
|
||||
RUN addgroup --gid 1000 minecraft \
|
||||
&& adduser --system --shell /bin/false --uid 1000 --ingroup minecraft --home /data minecraft
|
||||
|
||||
COPY files/sudoers* /etc/sudoers.d
|
||||
|
||||
@@ -31,9 +29,9 @@ EXPOSE 25565 25575
|
||||
|
||||
# hook into docker BuildKit --platform support
|
||||
# see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
|
||||
ARG TARGETOS=linux
|
||||
ARG TARGETARCH=amd64
|
||||
ARG TARGETVARIANT=""
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
ARG EASY_ADD_VER=0.7.1
|
||||
ADD https://github.com/itzg/easy-add/releases/download/${EASY_ADD_VER}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add
|
||||
@@ -67,11 +65,10 @@ COPY log4j2.xml /tmp/log4j2.xml
|
||||
WORKDIR /data
|
||||
|
||||
ENV UID=1000 GID=1000 \
|
||||
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
|
||||
MEMORY="1G" \
|
||||
TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED SPONGEBRANCH=STABLE SPONGEVERSION= FABRICVERSION=LATEST LEVEL=world \
|
||||
PVP=true DIFFICULTY=easy ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
|
||||
LEVEL_TYPE=DEFAULT SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
|
||||
REPLACE_ENV_VARIABLES="FALSE" ENV_VARIABLE_PREFIX="CFG_" \
|
||||
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 AUTOPAUSE_PERIOD=10
|
||||
|
||||
COPY start* /
|
||||
|
||||
126
README.md
126
README.md
@@ -11,7 +11,7 @@ latest snapshot. See the _Versions_ section below for more information.
|
||||
|
||||
To simply use the latest stable version, run
|
||||
|
||||
docker run -d -p 25565:25565 --name mc itzg/minecraft-server
|
||||
docker run -d -p 25565:25565 --name mc -e EULA=TRUE itzg/minecraft-server
|
||||
|
||||
where the standard server port, 25565, will be exposed on your host machine.
|
||||
|
||||
@@ -35,6 +35,7 @@ With that you can easily view the logs, stop, or re-start the container:
|
||||
docker stop mc
|
||||
|
||||
docker start mc
|
||||
*Be sure to always include `-e EULA=TRUE` in your commands, as Mojang/Microsoft requires EULA acceptance.*
|
||||
|
||||
## Looking for a Bedrock Dedicated Server
|
||||
|
||||
@@ -176,6 +177,8 @@ You can also query the container's health in a script friendly way:
|
||||
healthy
|
||||
```
|
||||
|
||||
Some orchestration systems, such as Portainer, don't allow for disabling the default `HEALTHCHECK` declared by this image. In those cases you can approximate the disabling of healthchecks by setting the environment variable `DISABLE_HEALTHCHECK` to `true`.
|
||||
|
||||
## Autopause (experimental)
|
||||
|
||||
### Description
|
||||
@@ -267,10 +270,20 @@ the `/path/on/host` folder contents look like:
|
||||
├── ops.json
|
||||
├── server.properties
|
||||
├── whitelist.json
|
||||
├── worlds
|
||||
│ └── ... PLACE MAPS IN THEIR OWN FOLDERS HERE ...
|
||||
└── ...
|
||||
```
|
||||
|
||||
If you add mods while the container is running, you'll need to restart it to pick those
|
||||
Providing a presistent `/data` mount is a good idea, both to persist the game world and to allow for the manual configuration which is sometimes needed.
|
||||
|
||||
For instance, imagine a scenario when the initial launch has completed, but you now want to change the worldmap for your server.
|
||||
|
||||
Assuming you have a shared directory to your container, you can then (after first launch) drag and drop your premade maps or worlds into the `\worlds\` directory. **Note:** each world should be placed in its own folder under the `\worlds\` directory.
|
||||
|
||||
Once your maps are in the proper path, you can then specify which map the server uses by changing the `level-name` value in `server.properties` to match the name of your map.
|
||||
|
||||
If you add mods or make changes to `server.properties` while the container is running, you'll need to restart it to pick those
|
||||
up:
|
||||
|
||||
docker stop mc
|
||||
@@ -289,6 +302,8 @@ This works well if you want to have a common set of modules in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
|
||||
|
||||
|
||||
### Replacing variables inside configs
|
||||
|
||||
Sometimes you have mods or plugins that require configuration information that is only available at runtime.
|
||||
@@ -306,7 +321,7 @@ defined environment variables. Variables that you want to replace need to be wra
|
||||
inside `${YOUR_VARIABLE}` curly brackets and prefixed with a dollar sign. This is the regular
|
||||
syntax for enviromment variables inside strings or config files.
|
||||
|
||||
Optionally you can also define a prefix to only match predefined enviroment variables.
|
||||
Optionally you can also define a prefix to only match predefined environment variables.
|
||||
|
||||
`ENV_VARIABLE_PREFIX="CFG_"` <-- this is the default prefix
|
||||
|
||||
@@ -322,6 +337,14 @@ There are some limitations to what characters you can use.
|
||||
Variables will be replaced in files with the following extensions:
|
||||
`.yml`, `.yaml`, `.txt`, `.cfg`, `.conf`, `.properties`.
|
||||
|
||||
Specific files can be excluded by listing their name (without path) in the variable `REPLACE_ENV_VARIABLES_EXCLUDES`.
|
||||
|
||||
Paths can be excluded by listing them in the variable `REPLACE_ENV_VARIABLES_EXCLUDE_PATHS`. Path
|
||||
excludes are recursive. Here is an example:
|
||||
```
|
||||
REPLACE_ENV_VARIABLES_EXCLUDE_PATHS="/data/plugins/Essentials/userdata /data/plugins/MyPlugin"
|
||||
```
|
||||
|
||||
Here is a full example where we want to replace values inside a `database.yml`.
|
||||
|
||||
```yml
|
||||
@@ -380,7 +403,7 @@ secrets:
|
||||
The content of `db_password`:
|
||||
|
||||
ug23u3bg39o-ogADSs
|
||||
|
||||
|
||||
## Running a Bukkit/Spigot server
|
||||
|
||||
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT` or `-e TYPE=SPIGOT` to your command-line.
|
||||
@@ -396,45 +419,7 @@ If you are hosting your own copy of Bukkit/Spigot you can override the download
|
||||
|
||||
You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true`
|
||||
|
||||
You can install Bukkit plugins in two ways...
|
||||
|
||||
### Using the /data volume
|
||||
|
||||
This is the easiest way if you are using a persistent `/data` mount.
|
||||
|
||||
To do this, you will need to attach the container's `/data` directory
|
||||
(see "Attaching data directory to host filesystem”).
|
||||
Then, you can add plugins to the `/path/on/host/plugins` folder you chose. From the example above,
|
||||
the `/path/on/host` folder contents look like:
|
||||
|
||||
```
|
||||
/path/on/host
|
||||
├── plugins
|
||||
│ └── ... INSTALL PLUGINS HERE ...
|
||||
├── ops.json
|
||||
├── server.properties
|
||||
├── whitelist.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
If you add plugins while the container is running, you'll need to restart it to pick those
|
||||
up:
|
||||
|
||||
docker stop mc
|
||||
docker start mc
|
||||
|
||||
### Using separate mounts
|
||||
|
||||
This is the easiest way if you are using an ephemeral `/data` filesystem,
|
||||
or downloading a world with the `WORLD` option.
|
||||
|
||||
There is one additional volume that can be mounted; `/plugins`.
|
||||
Any files in this filesystem will be copied over to the main
|
||||
`/data/plugins` filesystem before starting Minecraft.
|
||||
|
||||
This works well if you want to have a common set of plugins in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
If you have attached a host directory to the `/data` volume, then you can install plugins within the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up.
|
||||
|
||||
## Running a PaperSpigot server
|
||||
|
||||
@@ -451,48 +436,10 @@ If you are hosting your own copy of PaperSpigot you can override the download UR
|
||||
|
||||
- -e PAPER_DOWNLOAD_URL=<url>
|
||||
|
||||
You can install Bukkit plugins in two ways...
|
||||
|
||||
An example compose file is provided at
|
||||
[examples/docker-compose-paper.yml](examples/docker-compose-paper.yml).
|
||||
|
||||
### Using the /data volume
|
||||
|
||||
This is the easiest way if you are using a persistent `/data` mount.
|
||||
|
||||
To do this, you will need to attach the container's `/data` directory
|
||||
(see "Attaching data directory to host filesystem”).
|
||||
Then, you can add plugins to the `/path/on/host/plugins` folder you chose. From the example above,
|
||||
the `/path/on/host` folder contents look like:
|
||||
|
||||
```
|
||||
/path/on/host
|
||||
├── plugins
|
||||
│ └── ... INSTALL PLUGINS HERE ...
|
||||
├── ops.json
|
||||
├── server.properties
|
||||
├── whitelist.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
If you add plugins while the container is running, you'll need to restart it to pick those
|
||||
up:
|
||||
|
||||
docker stop mc
|
||||
docker start mc
|
||||
|
||||
### Using separate mounts
|
||||
|
||||
This is the easiest way if you are using an ephemeral `/data` filesystem,
|
||||
or downloading a world with the `WORLD` option.
|
||||
|
||||
There is one additional volume that can be mounted; `/plugins`.
|
||||
Any files in this filesystem will be copied over to the main
|
||||
`/data/plugins` filesystem before starting Minecraft.
|
||||
|
||||
This works well if you want to have a common set of plugins in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
If you have attached a host directory to the `/data` volume, then you can install plugins via the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up.
|
||||
|
||||
## Running a Tuinity server
|
||||
|
||||
@@ -579,6 +526,10 @@ The following example uses `/modpacks` as the container path as the pre-download
|
||||
-e CF_SERVER_MOD=/modpacks/SkyFactory_4_Server_4.1.0.zip \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
|
||||
#### Buggy start scripts
|
||||
|
||||
Some modpacks have buggy or overly complex start scripts. You can avoid using the bundled start script and use this image's standard server-starting logic by adding `-e USE_MODPACK_START_SCRIPT=false`.
|
||||
|
||||
### Fixing "unable to launch forgemodloader"
|
||||
|
||||
If your server's modpack fails to load with an error [like this](https://support.feed-the-beast.com/t/cant-start-crashlanding-server-unable-to-launch-forgemodloader/6028/2):
|
||||
@@ -670,6 +621,12 @@ This works well if you want to have a common set of modules in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
|
||||
## Deploying plugins from attached volume
|
||||
|
||||
There is one additional volume that can be mounted; `/plugins`. Any files in this filesystem will be copied over to the main `/data/plugins` filesystem before starting Minecraft. Set `PLUGINS_SYNC_UPDATE=false` if you want files from `/plugins` to take precedence over newer files in `/data/plugins`.
|
||||
|
||||
This works well if you want to have a common set of plugins in a separate location, but still have multiple worlds with different server requirements in either persistent volumes or a downloadable archive.
|
||||
|
||||
## Running with a custom server JAR
|
||||
|
||||
If you would like to run a custom server JAR, set `-e TYPE=CUSTOM` and pass the custom server
|
||||
@@ -975,7 +932,7 @@ For example (just the `-e` bits):
|
||||
|
||||
You can set a link to a custom resource pack and set it's checksum using the `RESOURCE_PACK` and `RESOURCE_PACK_SHA1` options respectively, the default is blank:
|
||||
|
||||
docker run -d -e 'RESROUCE_PACK=http\://link.com/to/pack.zip?\=1' -e 'RESOURCE_PACK_SHA1=d5db29cd03a2ed055086cef9c31c252b4587d6d0'
|
||||
docker run -d -e 'RESOURCE_PACK=http\://link.com/to/pack.zip?\=1' -e 'RESOURCE_PACK_SHA1=d5db29cd03a2ed055086cef9c31c252b4587d6d0'
|
||||
|
||||
**NOTE:** `:` and `=` must be escaped using `\`. The checksum plain-text hexadecimal.
|
||||
|
||||
@@ -1013,6 +970,9 @@ read-only volume attachment to ensure the clone source remains pristine.
|
||||
docker run ... -v $HOME/worlds:/worlds:ro -e WORLD=/worlds/basic
|
||||
```
|
||||
|
||||
### Overwrite world on start
|
||||
The world will only be downloaded or copied if it doesn't exist already. Set `FORCE_WORLD_COPY=TRUE` to force overwrite the world on every server start.
|
||||
|
||||
### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers
|
||||
|
||||
Like the `WORLD` option above, you can specify the URL of a "mod pack"
|
||||
|
||||
0
docs/.gitkeep
Normal file
0
docs/.gitkeep
Normal file
@@ -4,7 +4,7 @@
|
||||
|
||||
. /start-utils
|
||||
|
||||
sudo /usr/sbin/knockd -c /autopause/knockd-config.cfg -d
|
||||
sudo /usr/sbin/knockd -c /tmp/knockd-config.cfg -d
|
||||
if [ $? -ne 0 ] ; then
|
||||
while :
|
||||
do
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }')" =~ ^T.*$ ]]; then
|
||||
if isTrue "${DISABLE_HEALTHCHECK}"; then
|
||||
echo "Healthcheck disabled"
|
||||
exit 0
|
||||
elif isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }')" =~ ^T.*$ ]]; then
|
||||
echo "Java process suspended by Autopause function"
|
||||
exit 0
|
||||
else
|
||||
|
||||
7
start
7
start
@@ -36,16 +36,11 @@ if [ $(id -u) = 0 ]; then
|
||||
chown -R ${runAsUser}:${runAsGroup} /data
|
||||
fi
|
||||
|
||||
if [[ $(stat -c "%u" /autopause) != $UID ]]; then
|
||||
log "Changing ownership of /autopause to $UID ..."
|
||||
chown -R ${runAsUser}:${runAsGroup} /autopause
|
||||
fi
|
||||
|
||||
if [[ ${SKIP_NSSWITCH_CONF^^} != TRUE ]]; then
|
||||
echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
fi
|
||||
|
||||
exec su-exec ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
|
||||
exec gosu ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
|
||||
else
|
||||
exec ${SCRIPTS:-/}start-configuration $@
|
||||
fi
|
||||
|
||||
@@ -4,18 +4,20 @@
|
||||
|
||||
log "Autopause functionality enabled"
|
||||
|
||||
cp /autopause/knockd-config.cfg /tmp/knockd-config.cfg
|
||||
|
||||
# update server port to listen to
|
||||
regseq="^\s*sequence\s*=\s*$SERVER_PORT\s*$"
|
||||
linenum=$(grep -nm1 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /autopause/knockd-config.cfg
|
||||
linenum=$(grep -nm1 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /tmp/knockd-config.cfg
|
||||
log "Updated server port in knockd config"
|
||||
fi
|
||||
# update rcon port to listen to
|
||||
regseq="^\s*sequence\s*=\s*$RCON_PORT\s*$"
|
||||
linenum=$(grep -nm2 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /autopause/knockd-config.cfg
|
||||
linenum=$(grep -nm2 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /tmp/knockd-config.cfg
|
||||
log "Updated rcon port in knockd config"
|
||||
fi
|
||||
|
||||
|
||||
@@ -7,9 +7,10 @@ shopt -s nullglob
|
||||
#umask 002
|
||||
export HOME=/data
|
||||
|
||||
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
|
||||
|
||||
if [ ! -e /data/eula.txt ]; then
|
||||
EULA="${EULA,,}"
|
||||
if [ "$EULA" != "true" ]; then
|
||||
if ! isTrue "$EULA"; then
|
||||
log ""
|
||||
log "Please accept the Minecraft EULA at"
|
||||
log " https://account.mojang.com/documents/minecraft_eula"
|
||||
@@ -19,24 +20,10 @@ if [ ! -e /data/eula.txt ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# Generated via Docker on $(date)" > /data/eula.txt
|
||||
|
||||
if ! echo "eula=$EULA" >> /data/eula.txt; then
|
||||
log "ERROR: unable to write eula to /data. Please make sure attached directory is writable by uid=${UID}"
|
||||
exit 2
|
||||
fi
|
||||
writeEula
|
||||
fi
|
||||
|
||||
|
||||
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
|
||||
|
||||
if ! touch /data/.verify_access; then
|
||||
log "ERROR: /data doesn't seem to be writable. Please make sure attached directory is writable by uid=$(id -u)"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
rm /data/.verify_access || true
|
||||
|
||||
if [[ $PROXY ]]; then
|
||||
export http_proxy="$PROXY"
|
||||
export https_proxy="$PROXY"
|
||||
@@ -45,6 +32,22 @@ if [[ $PROXY ]]; then
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
if [[ $RCON_PASSWORD_FILE ]]; then
|
||||
log ""
|
||||
if [ ! -e ${RCON_PASSWORD_FILE} ]; then
|
||||
log "Initial RCON password file ${RCON_PASSWORD_FILE} does not seems to exist."
|
||||
log "Please ensure your configuration."
|
||||
log "If you are using Docker Secrets feature, please check this for further information: "
|
||||
log " https://docs.docker.com/engine/swarm/secrets"
|
||||
log ""
|
||||
exit 1
|
||||
else
|
||||
RCON_PASSWORD=$(cat ${RCON_PASSWORD_FILE})
|
||||
export RCON_PASSWORD
|
||||
fi
|
||||
log ""
|
||||
fi
|
||||
|
||||
export SERVER_PROPERTIES=/data/server.properties
|
||||
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
|
||||
|
||||
@@ -55,11 +58,8 @@ case "X$VERSION" in
|
||||
XSNAPSHOT|Xsnapshot)
|
||||
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.snapshot')
|
||||
;;
|
||||
X[1-9]*)
|
||||
VANILLA_VERSION=$VERSION
|
||||
;;
|
||||
*)
|
||||
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.release')
|
||||
VANILLA_VERSION=$VERSION
|
||||
;;
|
||||
esac
|
||||
export VANILLA_VERSION
|
||||
@@ -95,8 +95,12 @@ case "${TYPE^^}" in
|
||||
exec ${SCRIPTS:-/}start-deployFabric "$@"
|
||||
;;
|
||||
|
||||
FTB|CURSEFORGE)
|
||||
exec ${SCRIPTS:-/}start-deployFTB "$@"
|
||||
FTBA)
|
||||
exec ${SCRIPTS:-/}start-deployFTBA "$@"
|
||||
;;
|
||||
|
||||
CURSEFORGE|FTB)
|
||||
exec ${SCRIPTS:-/}start-deployCF "$@"
|
||||
;;
|
||||
|
||||
VANILLA)
|
||||
@@ -129,8 +133,9 @@ case "${TYPE^^}" in
|
||||
|
||||
*)
|
||||
log "Invalid type: '$TYPE'"
|
||||
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA, CURSEFORGE, SPONGEVANILLA,"
|
||||
log " CUSTOM, CURSE_INSTANCE, MAGMA, MOHIST, CATSERVER"
|
||||
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
|
||||
log " CURSE_INSTANCE, CURSEFORGE, SPONGEVANILLA,"
|
||||
log " CUSTOM, MAGMA, MOHIST, CATSERVER"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
|
||||
@@ -62,8 +62,12 @@ function downloadSpigot {
|
||||
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
||||
fi
|
||||
|
||||
if [ -f $SERVER ]; then
|
||||
# tell curl to only download when newer
|
||||
zarg="-z $SERVER"
|
||||
fi
|
||||
log "Downloading $match from $downloadUrl ..."
|
||||
curl -fsSL -o $SERVER "$downloadUrl"
|
||||
curl -fsSL -o $SERVER $zarg "$downloadUrl"
|
||||
if [[ $? != 0 || $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
|
||||
cat <<EOF
|
||||
|
||||
@@ -89,12 +93,12 @@ case "$TYPE" in
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
|
||||
buildSpigotFromSource
|
||||
else
|
||||
downloadSpigot
|
||||
fi
|
||||
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
|
||||
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
buildSpigotFromSource
|
||||
fi
|
||||
else
|
||||
downloadSpigot
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for operations below
|
||||
@@ -102,4 +106,4 @@ export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,26 +1,77 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
export FTB_BASE_DIR=/data/FeedTheBeast
|
||||
legacyJavaFixerUrl=http://ftb.cursecdn.com/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
|
||||
export TYPE=FEED-THE-BEAST
|
||||
export TYPE=CURSEFORGE
|
||||
|
||||
FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
|
||||
|
||||
log "Looking for Feed-The-Beast / CurseForge server modpack."
|
||||
if [[ -z $FTB_SERVER_MOD ]]; then
|
||||
log "Environment variable FTB_SERVER_MOD not set."
|
||||
log "Set FTB_SERVER_MOD to the file name of the FTB server modpack."
|
||||
log "(And place the modpack in the /data directory.)"
|
||||
requireVar FTB_SERVER_MOD
|
||||
|
||||
if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
|
||||
if ! [ -f ${FTB_SERVER_MOD} ]; then
|
||||
log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
needsInstall=true
|
||||
installMarker=/data/.curseforge-installed
|
||||
if [ -f $installMarker ]; then
|
||||
if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then
|
||||
log "Upgrading modpack"
|
||||
|
||||
serverJar=$(find ${FTB_BASE_DIR} -not -name "forge*installer.jar" -name "forge*.jar")
|
||||
if [[ "${serverJar}" ]]; then
|
||||
rm -rf $(dirname "${serverJar}")/{mods,*.jar,libraries,resources,scripts}
|
||||
fi
|
||||
else
|
||||
needsInstall=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if $needsInstall; then
|
||||
log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..."
|
||||
mkdir -p ${FTB_BASE_DIR}
|
||||
unzip -o ${FTB_SERVER_MOD} -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
|
||||
|
||||
forgeInstallerJar=$(find ${FTB_BASE_DIR} -name "forge*installer.jar")
|
||||
if [[ -z "${forgeInstallerJar}" ]]; then
|
||||
log "ERROR Unable to find forge installer in modpack."
|
||||
log " Make sure you downloaded the server files."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
log "Installing forge server"
|
||||
(cd $(dirname "${forgeInstallerJar}"); java -jar $(basename ${forgeInstallerJar}) --installServer) | awk '{printf "."} END {print ""}'
|
||||
|
||||
echo "${FTB_SERVER_MOD}" > $installMarker
|
||||
fi
|
||||
|
||||
export SERVER=$(find ${FTB_BASE_DIR} -not -name "forge*installer.jar" -name "forge*.jar")
|
||||
if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then
|
||||
log "ERROR unable to locate installed forge server jar"
|
||||
isDebugging && find ${FTB_BASE_DIR} -name "forge*.jar"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
export FTB_DIR=$(dirname "${SERVER}")
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
fi
|
||||
|
||||
entryScriptExpr="
|
||||
-name ServerStart.sh
|
||||
-o -name serverstart.sh
|
||||
-o -name ServerStartLinux.sh
|
||||
-o -name LaunchServer.sh
|
||||
-o -name server-start.sh
|
||||
-o -name startserver.sh
|
||||
-o -name StartServer.sh
|
||||
"
|
||||
|
||||
if [[ -d ${FTB_BASE_DIR} ]]; then
|
||||
@@ -135,4 +186,4 @@ elif [ -e "${FTB_DIR}/Install.sh" ]; then
|
||||
fi
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
@@ -29,4 +29,4 @@ fi
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World "$@"
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld "$@"
|
||||
|
||||
@@ -28,4 +28,4 @@ fi
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
72
start-deployFTBA
Normal file
72
start-deployFTBA
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
|
||||
ftbInstallMarker=".ftb-installed"
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
set -e
|
||||
|
||||
if ! [[ -v FTB_MODPACK_ID ]]; then
|
||||
log "ERROR FTB_MODPACK_ID is required with TYPE=FTB"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ ${FTB_MODPACK_ID} =~ [0-9]+ ]]; then
|
||||
log "ERROR FTB_MODPACK_ID needs to be numeric"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ -v FTB_MODPACK_VERSION_ID ]]; then
|
||||
if ! FTB_MODPACK_VERSION_ID=$(curl -fsSL https://api.modpacks.ch/public/modpack/${FTB_MODPACK_ID} | jq -r '.versions | sort_by(.updated)[-1].id'); then
|
||||
log "ERROR unable to resolve latest modpack version ID for modpack ${FTB_MODPACK_ID}"
|
||||
exit 1
|
||||
fi
|
||||
elif ! [[ ${FTB_MODPACK_VERSION_ID} =~ [0-9]+ ]]; then
|
||||
log "ERROR FTB_MODPACK_VERSION_ID needs to be numeric"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -f "${ftbInstallMarker}" ] || [ $(cat "${ftbInstallMarker}") != "${FTB_MODPACK_ID}=${FTB_MODPACK_VERSION_ID}" ]; then
|
||||
ftbInstaller=/data/ftb-installer
|
||||
if ! [[ -f "${ftbInstaller}" ]]; then
|
||||
log "Downloading FTB installer"
|
||||
curl -fsSL https://api.modpacks.ch/public/modpack/1/1/server/linux -o "${ftbInstaller}"
|
||||
chmod +x "${ftbInstaller}"
|
||||
fi
|
||||
|
||||
rm -rf forge*jar mods config libraries defaultconfigs changelogs
|
||||
|
||||
log "Installing modpack ID ${FTB_MODPACK_ID}, version ID ${FTB_MODPACK_VERSION_ID}"
|
||||
${ftbInstaller} ${FTB_MODPACK_ID} ${FTB_MODPACK_VERSION_ID} --noscript --auto
|
||||
rm -f forge*installer.jar
|
||||
|
||||
echo "${FTB_MODPACK_ID}=${FTB_MODPACK_VERSION_ID}" > ${ftbInstallMarker}
|
||||
|
||||
writeEula
|
||||
else
|
||||
log "FTB modpack ID ${FTB_MODPACK_ID}, version ID ${FTB_MODPACK_VERSION_ID} is ready to go"
|
||||
fi
|
||||
|
||||
isDebugging && cat version.json
|
||||
forgeVersion=$(jq -r '.targets[] | select(.name == "forge") | .version' version.json)
|
||||
mcVersion=$(jq -r '.targets[] | select(.name == "minecraft") | .version' version.json)
|
||||
|
||||
variants=(
|
||||
forge-${mcVersion}-${forgeVersion}.jar
|
||||
forge-${mcVersion}-${forgeVersion}-universal.jar
|
||||
forge-${mcVersion}-${forgeVersion}-${mcVersion}-universal.jar
|
||||
)
|
||||
for f in ${variants[@]}; do
|
||||
if [ -f $f ]; then
|
||||
export SERVER=$f
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ! [ -v SERVER ]; then
|
||||
log "ERROR unable to locate the installed forge server jar"
|
||||
ls *.jar
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
@@ -75,4 +75,4 @@ else
|
||||
fi
|
||||
|
||||
# Contineut to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -113,4 +113,4 @@ else
|
||||
fi
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -15,4 +15,4 @@ fi
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -40,4 +40,4 @@ fi
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World "$@"
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld "$@"
|
||||
|
||||
@@ -5,19 +5,20 @@
|
||||
: ${PAPERBUILD:=latest}
|
||||
export SERVER=paper_server-${VANILLA_VERSION}-${PAPERBUILD}.jar
|
||||
|
||||
if [ ! -f "$SERVER" ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
downloadUrl=${PAPER_DOWNLOAD_URL:-https://papermc.io/api/v1/paper/${VANILLA_VERSION}/${PAPERBUILD}/download}
|
||||
log "Downloading Paper $VANILLA_VERSION (build $PAPERBUILD) from $downloadUrl ..."
|
||||
curl -fsSL -o "$SERVER" "$downloadUrl"
|
||||
if [ ! -f "$SERVER" ]; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
if [ -f "$SERVER" ] && ! isTrue "$FORCE_REDOWNLOAD"; then
|
||||
zarg="-z '$SERVER'"
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for operations below
|
||||
downloadUrl=${PAPER_DOWNLOAD_URL:-https://papermc.io/api/v1/paper/${VANILLA_VERSION}/${PAPERBUILD}/download}
|
||||
log "Downloading Paper $VANILLA_VERSION (build $PAPERBUILD) from $downloadUrl ..."
|
||||
if ! curl -fsSL -o "$SERVER" $zarg "$downloadUrl"; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for downstream operations
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -36,4 +36,4 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
fi
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -24,4 +24,4 @@ fi
|
||||
export TYPE=SPIGOT
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -26,6 +26,9 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
if [ $result != 0 ]; then
|
||||
log "ERROR failed to obtain version manifest from $versionManifestUrl ($result)"
|
||||
exit 1
|
||||
elif [ $serverDownloadUrl = null ]; then
|
||||
log "ERROR version $VANILLA_VERSION does not provide a server download"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
debug "Downloading server from $serverDownloadUrl"
|
||||
@@ -43,4 +46,4 @@ fi
|
||||
isDebugging && ls -l
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -2,8 +2,26 @@
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if [ "${REPLACE_ENV_VARIABLES^^}" = "TRUE" ]; then
|
||||
: ${ENV_VARIABLE_PREFIX:=CFG_}
|
||||
|
||||
if isTrue "${REPLACE_ENV_VARIABLES}"; then
|
||||
log "Replacing env variables in configs that match the prefix $ENV_VARIABLE_PREFIX..."
|
||||
|
||||
# File excludes
|
||||
fileExcludes=
|
||||
for f in ${REPLACE_ENV_VARIABLES_EXCLUDES}; do
|
||||
fileExcludes="${fileExcludes} -not -name $f"
|
||||
done
|
||||
|
||||
# Directory excludes (recursive)
|
||||
dirExcludes=$(join_by " -o -path " ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS})
|
||||
if [[ $dirExcludes ]]; then
|
||||
dirExcludes=" -type d ( -path ${dirExcludes} ) -prune -o"
|
||||
fi
|
||||
|
||||
isDebugging && echo "Using find file exclusions: $fileExcludes"
|
||||
isDebugging && echo "Using find directory exclusions: $dirExcludes"
|
||||
|
||||
while IFS='=' read -r name value ; do
|
||||
# check if name of env variable matches the prefix
|
||||
# sanity check environment variables to avoid code injections
|
||||
@@ -17,9 +35,12 @@ if [ "${REPLACE_ENV_VARIABLES^^}" = "TRUE" ]; then
|
||||
fi
|
||||
|
||||
log "Replacing $name with $value ..."
|
||||
find /data/ -type f \
|
||||
find /data/ \
|
||||
$dirExcludes \
|
||||
-type f \
|
||||
\( -name "*.yml" -or -name "*.yaml" -or -name "*.txt" -or -name "*.cfg" \
|
||||
-or -name "*.conf" -or -name "*.properties" \) \
|
||||
$fileExcludes \
|
||||
-exec sed -i 's#${'"$name"'}#'"$value"'#g' {} \;
|
||||
fi
|
||||
done < <(env)
|
||||
@@ -24,4 +24,4 @@ case "X$MODCONFIG" in
|
||||
esac
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetup04ServerProperties $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupPlugins $@
|
||||
@@ -18,42 +18,60 @@ fi
|
||||
|
||||
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack
|
||||
if [[ "$MODPACK" ]]; then
|
||||
EFFECTIVE_MODPACK_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MODPACK)
|
||||
case "X$EFFECTIVE_MODPACK_URL" in
|
||||
X[Hh][Tt][Tt][Pp]*.zip)
|
||||
if isURL "${MODPACK}"; then
|
||||
if [[ "${MODPACK}" == *.zip ]]; then
|
||||
downloadUrl="${MODPACK}"
|
||||
else
|
||||
downloadUrl=$(curl -Ls -o /dev/null -w %{url_effective} $MODPACK)
|
||||
if ! [[ $downloadUrl == *.zip ]]; then
|
||||
log "ERROR Invalid URL given for MODPACK: $downloadUrl resolved from $MODPACK"
|
||||
log " Must be HTTP or HTTPS and a ZIP file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Downloading mod/plugin pack via HTTP"
|
||||
log " from $EFFECTIVE_MODPACK_URL ..."
|
||||
if ! curl -sSL -o /tmp/modpack.zip "$EFFECTIVE_MODPACK_URL"; then
|
||||
log "ERROR: failed to download from $EFFECTIVE_MODPACK_URL"
|
||||
log " from $downloadUrl ..."
|
||||
if ! curl -sSL -o /tmp/modpack.zip "$downloadUrl"; then
|
||||
log "ERROR: failed to download from $downloadUrl"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
mkdir -p /data/plugins
|
||||
if ! unzip -o -d /data/plugins /tmp/modpack.zip; then
|
||||
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
|
||||
log "ERROR: failed to unzip the modpack from $downloadUrl"
|
||||
fi
|
||||
else
|
||||
mkdir -p /data/mods
|
||||
if ! unzip -o -d /data/mods /tmp/modpack.zip; then
|
||||
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
|
||||
log "ERROR: failed to unzip the modpack from $downloadUrl"
|
||||
fi
|
||||
fi
|
||||
rm -f /tmp/modpack.zip
|
||||
;;
|
||||
*)
|
||||
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a ZIP file"
|
||||
;;
|
||||
esac
|
||||
|
||||
else
|
||||
log "ERROR Invalid URL given for MODPACK: $MODPACK"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# If supplied with a URL for a plugin download it.
|
||||
if [[ "$MODS" ]]; then
|
||||
for i in ${MODS//,/ }
|
||||
do
|
||||
EFFECTIVE_MOD_URL=$(curl -Ls -o /dev/null -w %{url_effective} $i)
|
||||
case "X$EFFECTIVE_MOD_URL" in
|
||||
X[Hh][Tt][Tt][Pp]*.jar)
|
||||
for i in ${MODS//,/ }
|
||||
do
|
||||
if isURL $i; then
|
||||
if [[ $i == *.jar ]]; then
|
||||
EFFECTIVE_MOD_URL=$i
|
||||
else
|
||||
EFFECTIVE_MOD_URL=$(curl -Ls -o /dev/null -w %{url_effective} $i)
|
||||
if ! [[ $EFFECTIVE_MOD_URL == *.jar ]]; then
|
||||
log "ERROR Invalid URL given in MODS: $EFFECTIVE_MOD_URL resolved from $i"
|
||||
log " Must be HTTP or HTTPS and a JAR file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Downloading mod/plugin via HTTP"
|
||||
log " from $EFFECTIVE_MOD_URL ..."
|
||||
if ! curl -sSL -o /tmp/${EFFECTIVE_MOD_URL##*/} $EFFECTIVE_MOD_URL; then
|
||||
@@ -69,12 +87,12 @@ do
|
||||
mv /tmp/${EFFECTIVE_MOD_URL##*/} /data/mods/${EFFECTIVE_MOD_URL##*/}
|
||||
fi
|
||||
rm -f /tmp/${EFFECTIVE_MOD_URL##*/}
|
||||
;;
|
||||
*)
|
||||
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a JAR file"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
else
|
||||
log "ERROR Invalid URL given in MODS: $i"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "$MANIFEST" ]]; then
|
||||
@@ -154,4 +172,4 @@ if [[ "${GENERIC_PACK}" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetup03Modconfig $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupModconfig $@
|
||||
23
start-finalSetupPlugins
Executable file
23
start-finalSetupPlugins
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
: ${PLUGINS_SYNC_UPDATE:=true}
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
if [ -d /plugins ]; then
|
||||
case ${TYPE} in
|
||||
SPIGOT|BUKKIT|PAPER)
|
||||
mkdir -p /data/plugins
|
||||
log "Copying plugins over..."
|
||||
if isTrue ${PLUGINS_SYNC_UPDATE}; then
|
||||
updateArg="--update"
|
||||
fi
|
||||
# Copy plugins over using rsync to allow deeply nested updates of plugins
|
||||
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs $updateArg /plugins /data
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetupServerProperties $@
|
||||
@@ -206,4 +206,4 @@ if isDebugging; then
|
||||
cat /data/server.properties
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetup05EnvVariables $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupEnvVariables $@
|
||||
@@ -10,7 +10,7 @@ else
|
||||
worldDest=/data/$LEVEL
|
||||
fi
|
||||
|
||||
if [[ "$WORLD" ]] && [ ! -d "$worldDest" ]; then
|
||||
if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then
|
||||
if isURL $WORLD; then
|
||||
curl -fsSL "$WORLD" -o /tmp/world.zip
|
||||
zipSrc=/tmp/world.zip
|
||||
@@ -37,10 +37,10 @@ if [[ "$WORLD" ]] && [ ! -d "$worldDest" ]; then
|
||||
log "ERROR invalid world content"
|
||||
exit 1
|
||||
fi
|
||||
mv "$baseDir" "$worldDest"
|
||||
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest"
|
||||
else
|
||||
log "Cloning world directory from $WORLD ..."
|
||||
cp -r "$WORLD" "$worldDest"
|
||||
rsync --recursive --delete "${WORLD%/}"/ "$worldDest"
|
||||
fi
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
@@ -51,4 +51,4 @@ if [[ "$WORLD" ]] && [ ! -d "$worldDest" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetup02Modpack $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupModpack $@
|
||||
@@ -66,18 +66,6 @@ do
|
||||
fi
|
||||
done
|
||||
|
||||
case ${TYPE} in
|
||||
SPIGOT|BUKKIT|PAPER)
|
||||
mkdir -p /data/plugins
|
||||
if [ -d /plugins ]; then
|
||||
log "Copying plugins over..."
|
||||
# Copy plugins over using rsync to allow deeply nested updates of plugins
|
||||
# only updates files if the source file is newer and print updated files
|
||||
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs --update /plugins /data
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
EXTRA_ARGS=""
|
||||
# Optional disable console
|
||||
if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
|
||||
@@ -170,49 +158,60 @@ if isTrue "${DEBUG_MEMORY}"; then
|
||||
free -m
|
||||
fi
|
||||
|
||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||
|
||||
function copyFilesForCurseForge() {
|
||||
# copy player modification files unconditionally since their
|
||||
# processing into json is additive anyway
|
||||
[ -f /data/ops.txt ] && cp -f /data/ops.txt ${FTB_DIR}/
|
||||
[ -f /data/white-list.txt ] && cp -f /data/white-list.txt ${FTB_DIR}/
|
||||
|
||||
if [ ! -e "${FTB_DIR}/server-icon.png" -a -e /data/server-icon.png ]; then
|
||||
cp -f /data/server-icon.png ${FTB_DIR}/
|
||||
fi
|
||||
|
||||
cp -f /data/eula.txt "${FTB_DIR}/"
|
||||
}
|
||||
|
||||
mcServerRunnerArgs="--stop-duration 60s"
|
||||
if [[ ${TYPE} == "CURSE_INSTANCE" ]]; then
|
||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${mcServerRunnerArgs} \
|
||||
--cf-instance-file "${CURSE_INSTANCE_JSON}" \
|
||||
java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar _SERVERJAR_ "$@" $EXTRA_ARGS
|
||||
elif [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
|
||||
mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash"
|
||||
elif [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then
|
||||
copyFilesForCurseForge
|
||||
|
||||
if [ ! -e "${FTB_DIR}/ops.json" -a -e /data/ops.txt ]; then
|
||||
cp -f /data/ops.txt ${FTB_DIR}/
|
||||
fi
|
||||
cd "${FTB_DIR}"
|
||||
log "Starting CurseForge server in ${FTB_DIR}..."
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${bootstrapArgs} ${mcServerRunnerArgs} java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar $(basename "${SERVER}") "$@" $EXTRA_ARGS
|
||||
elif [[ ${TYPE} == "CURSEFORGE" ]]; then
|
||||
mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash"
|
||||
|
||||
if [ ! -e "${FTB_DIR}/whitelist.json" -a -e /data/white-list.txt ]; then
|
||||
cp -f /data/white-list.txt ${FTB_DIR}/
|
||||
fi
|
||||
copyFilesForCurseForge
|
||||
|
||||
if [ ! -e "${FTB_DIR}/server-icon.png" -a -e /data/server-icon.png ]; then
|
||||
cp -f /data/server-icon.png ${FTB_DIR}/
|
||||
fi
|
||||
|
||||
cp -f /data/eula.txt "${FTB_DIR}/"
|
||||
|
||||
cat > "${FTB_DIR}/settings-local.sh" <<EOF
|
||||
cat > "${FTB_DIR}/settings-local.sh" <<EOF
|
||||
export MIN_RAM="${INIT_MEMORY}"
|
||||
export MAX_RAM="${MAX_MEMORY}"
|
||||
export JAVA_PARAMETERS="${JVM_XX_OPTS} -Xms${INIT_MEMORY} ${JVM_OPTS} $expandedDOpts"
|
||||
EOF
|
||||
|
||||
# patch CurseForge cfg file, if present
|
||||
if [ -f "${FTB_DIR}/settings.cfg" ]; then
|
||||
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
|
||||
fi
|
||||
# patch CurseForge cfg file, if present
|
||||
if [ -f "${FTB_DIR}/settings.cfg" ]; then
|
||||
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
|
||||
fi
|
||||
|
||||
cd "${FTB_DIR}"
|
||||
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${mcServerRunnerArgs} "${FTB_SERVER_START}"
|
||||
cd "${FTB_DIR}"
|
||||
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${mcServerRunnerArgs} "${FTB_SERVER_START}"
|
||||
else
|
||||
# If we have a bootstrap.txt file... feed that in to the server stdin
|
||||
if [ -f /data/bootstrap.txt ]; then
|
||||
@@ -220,7 +219,6 @@ else
|
||||
fi
|
||||
|
||||
log "Starting the Minecraft server..."
|
||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
15
start-utils
15
start-utils
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
|
||||
|
||||
function isURL {
|
||||
local value=$1
|
||||
|
||||
@@ -106,4 +108,17 @@ requireVar() {
|
||||
log "ERROR: $1 is required to be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${!1}" ]; then
|
||||
log "ERROR: $1 is required to be set"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function writeEula() {
|
||||
if ! echo "# Generated via Docker on $(date)
|
||||
eula=${EULA,,}
|
||||
" > /data/eula.txt; then
|
||||
log "ERROR: unable to write eula to /data. Please make sure attached directory is writable by uid=${UID}"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -15,4 +15,4 @@ fi
|
||||
log "Resolved CURSE_INSTANCE_JSON as ${CURSE_INSTANCE_JSON}"
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetup01World "$@"
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld "$@"
|
||||
|
||||
17
tests/docker-compose.test.yml
Normal file
17
tests/docker-compose.test.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
sut:
|
||||
depends_on:
|
||||
- mc
|
||||
image: itzg/mc-monitor:0.6.0
|
||||
command: status --host mc --retry-interval 1s --retry-limit 120
|
||||
mc:
|
||||
restart: "no"
|
||||
build:
|
||||
context: ..
|
||||
cache_from:
|
||||
- itzg/minecraft-server:latest
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
|
||||
17
tests/test.sh
Executable file
17
tests/test.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
failed=false
|
||||
args="-f docker-compose.test.yml"
|
||||
docker-compose $args run sut || failed=true
|
||||
echo "
|
||||
Result: failed=$failed"
|
||||
|
||||
$failed && docker-compose $args logs mc
|
||||
docker-compose $args down -v
|
||||
|
||||
if $failed; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user