0

I want to use docker for a minecraft server. The thing is that I need to shut it down properly to save the world every 24 hours. And to make things more complicated: the people on the server need be informed about this.

So my idea was using "screen" in conjunction with "cron":

################################
### We use a java base image ###
################################
FROM openjdk:8 AS build

MAINTAINER me <me@me.com>

#################
### Arguments ###
#################
ARG PAPERSPIGOT_CI_URL=https://papermc.io/ci/job/Paper-1.13/lastSuccessfulBuild/artifact/paperclip.jar

##########################
### Download paperclip ###
##########################
ADD ${PAPERSPIGOT_CI_URL} /opt/minecraft/server/paperclip.jar

############################################
### Run paperclip and obtain patched jar ###
############################################
RUN cd /opt/minecraft/server/ \
    && java -jar paperclip.jar; exit 0

RUN cd /opt/minecraft/server/ \
    && mv cache/patched*.jar paperspigot.jar

###########################
### Running environment ###
###########################
FROM anapsix/alpine-java:latest

###########################
### Install screen      ###
###########################
RUN apk --update add screen

#########################
### Working directory ###
#########################
WORKDIR /data

###########################################
### Obtain runable jar from build stage ###
###########################################
COPY --from=build /opt/minecraft/server/paperspigot.jar /opt/minecraft/server/paperspigot.jar

########################
### Obtain starth.sh ###
########################
ADD start.sh /opt/minecraft/server/start.sh

########################
### Obtain restart.sh ###
########################
ADD restart.sh /opt/minecraft/server/restart.sh

###########################################
### Configure and run cron              ###
###########################################
COPY crontab /etc/cron/crontab
# Init cron
RUN crontab /etc/cron/crontab

CMD ["crond", "-f"]

###############
### Volumes ###
###############
VOLUME "/data"

#############################
### Expose minecraft port ###
#############################
EXPOSE 25565

######################################
### Entrypoint is the start script ###
######################################
WORKDIR /data
ENTRYPOINT sh /opt/minecraft/server/start.sh

This is the start.sh script that seems to work:

#/bin/sh
cd /data
/usr/bin/screen -S minecraft /opt/jdk1.8.0_192/jre/bin/java -jar -Xms800M -Xmx800M -Dcom.mojang.eula.agree=true /opt/minecraft/server/paperspigot.jar
screen -ls

This is the restart script triggered via the crontab. I think it never gets started:

#!/bin/sh
# me - V1.1 - 18.05.2018
# Minecraft Server restart
screen -Rd minecraft -X stuff "say Server is restarting in 30 seconds! $(printf '\r')"
sleep 23s
screen -Rd minecraft -X stuff "say Server is restarting in 7 seconds! $(printf '\r')"
sleep 1s
screen -Rd minecraft -X stuff "say Server is restarting in 6 seconds! $(printf '\r')"
sleep 1s
screen -Rd minecraft -X stuff "say Server is restarting in 5 seconds! $(printf '\r')"
sleep 1s
screen -Rd minecraft -X stuff "say Server is restarting in 4 seconds! $(printf '\r')"
sleep 1s
screen -Rd minecraft -X stuff "say Server is restarting in 3 seconds! $(printf '\r')"
sleep 1s
screen -Rd minecraft -X stuff "say Server is restarting in 2 seconds! $(printf '\r')"
sleep 1s
screen -Rd minecraft -X stuff "say Server is restarting in 1 second! $(printf '\r')"
sleep 1s
screen -Rd minecraft -X stuff "say Closing server...$(printf '\r')"
screen -Rd minecraft -X stuff "stop $(printf '\r')"
sleep 15s
# echo "Updating to most recent paperclip version."
# wget -q https://papermc.io/ci/job/Paper-1.13/lastSuccessfulBuild/artifact/paperclip.jar -O /home/pi/minecraft/paperclip.jar
echo "Restarting now."
/opt/minecraft/server/start.sh

This is the crontab which should start restart.sh every 5 minutes. Does not happen:

*/5 * * * * /opt/minecraft/server/restart.sh

Maybe this is the wrong way to do this. Maybe there is a much better way to connect somehow to the screen session or to restart the server with a message somehow. But I did not find anything online. Any idea?

Marc
  • 1,088
  • 8
  • 9
  • Is there any reason your script is handling the server announcements. Wouldn't an internal server code be better? Check if your pc time is nearing 12:00, and then if so, just warn players in server. – Frontear Dec 21 '18 at 03:28

2 Answers2

1

after some testing and reading I came to the conclusion that using cron inside the container is the wrong why to do it.

I start and restart the docker container with docker. Since it is so fast I dont need to inform the ppl on the server. And the server gets properly stopped.

Marc
  • 1,088
  • 8
  • 9
0

There are two possible problems here:

  1. the cron daemon may not be installed in your Docker image, and
  2. the cron job may be having problems locating executables in your Docker container

With regard to the first, I don't see anything installing cron in your Dockerfile. You probably want to check into the base image you're using - I know that I had to install it on an Ubuntu image I built a while back.

As for the second problem, the thing about running jobs in your crontab is that the environment is not what you expect it to be. Specifically, the $PATH variable, which the shell uses to find the commands you want to execute, is not set. As a result, many commands simply do not work because the shell doesn't know where to find them.

The "quick and dirty" way of fixing this is to ensure the $PATH variable is set in your crontab, by adding the following line:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

See this answer for more details.

Kryten
  • 15,230
  • 6
  • 45
  • 68