Using docker for production server
Using docker for production server
Hi
I'm developing our game with smartfox2x as gameserver, and making use of docker to simplify the deployment.
And the only way I can run smartfox server through docker is using sfs2x.sh script
As I search around the forum (for example viewtopic.php?t=22059), you suggest to only use sfs2x.sh script for development and sfs2x-service start for production
But the thing about sfs2x-service script is it stops right at the start and thus make the docker container to stop as well
To workaround it, I can add a tail -f /dev/null command behind and force the process to run forever.
But one thing is that I don't know if it's a good idea, because there maybe the case where the smartfox server has some issues and stop, but the docker container will not notice that and continue to run.
So my question is, do you have any better suggestion about running smartfox server through docker by using sfs2x-service script? (other than my workaround above)
I'm developing our game with smartfox2x as gameserver, and making use of docker to simplify the deployment.
And the only way I can run smartfox server through docker is using sfs2x.sh script
As I search around the forum (for example viewtopic.php?t=22059), you suggest to only use sfs2x.sh script for development and sfs2x-service start for production
But the thing about sfs2x-service script is it stops right at the start and thus make the docker container to stop as well
To workaround it, I can add a tail -f /dev/null command behind and force the process to run forever.
But one thing is that I don't know if it's a good idea, because there maybe the case where the smartfox server has some issues and stop, but the docker container will not notice that and continue to run.
So my question is, do you have any better suggestion about running smartfox server through docker by using sfs2x-service script? (other than my workaround above)
Re: Using docker for production server
Hi,
what version of SFS2X are you using and under which OS?
Are there any errors when using the sfs2x-service command? Have you checked the server side logs after running the command to see if there's any relevant error message?
Also have you modified any of the launch scripts?
Have you modified or replaced the embedded java runtime?
Thanks
what version of SFS2X are you using and under which OS?
Are there any errors when using the sfs2x-service command? Have you checked the server side logs after running the command to see if there's any relevant error message?
Also have you modified any of the launch scripts?
Have you modified or replaced the embedded java runtime?
Thanks
Re: Using docker for production server
Lapo wrote:what version of SFS2X are you using and under which OS?
It's the SFS2X latest version 2.18.0, and I run it on an EC2 instance with Amazon Linux 2 OS
Lapo wrote:Are there any errors when using the sfs2x-service command? Have you checked the server side logs after running the command to see if there's any relevant error message?
There is only the starting log of SFS2X, which is
Code: Select all
Starting sfs2x-service
There isn't even any java process running
I think it's because that's the way docker works. If the script uses to run the docker container stops, that docker container stops too, and also stops any of its child process
Lapo wrote:Also have you modified any of the launch scripts?
Have you modified or replaced the embedded java runtime?
Before 2.18.0, I had to replace the default jre with jre 11. But since updating to 2.18.0, I removed that, and used the default jre, as it's v11 and fit my needs.
No, I only modified the sfs2x.sh to change from using built-in jre to my jre (installed outside of SFS2X), but not the sfs2x-service script. And it's also removed since I updated to sfs2x 2.18.0
UPDATE:
I checked the sfs2x-service script and found out about the start-launchd parameter
It's almost the same with start parameter, except it prints out logs and only stop if sfs2x crash or stop itself
So I wonder should I use start-launchd parameter instead of start parameter?
Last edited by willan on 24 Dec 2021, 11:09, edited 1 time in total.
Re: Using docker for production server
Hi,
I have to premise this by saying that I am not very familiar with Docker. I know what it is and how it works (by virtualizing the OS rather than the hardware) but I've never used it.
So if you run the sfs2x-service start command it starts and dies immediately after?
I get that if you stop the docker container the process(es) associated with it will die, but I'd expect SFS2X to be able to run inside the container without issues. At least until the container is running.
Is it not the case? If it does run, then I am not sure I fully understand what the problem is.
Can you clarify?
Thanks
I have to premise this by saying that I am not very familiar with Docker. I know what it is and how it works (by virtualizing the OS rather than the hardware) but I've never used it.
There isn't even any java process running
It's because that's the way docker works
If the script uses to run the docker container stops, that docker container stops too, and also stops any of its child process
So if you run the sfs2x-service start command it starts and dies immediately after?
I get that if you stop the docker container the process(es) associated with it will die, but I'd expect SFS2X to be able to run inside the container without issues. At least until the container is running.
Is it not the case? If it does run, then I am not sure I fully understand what the problem is.
Can you clarify?
Thanks
Re: Using docker for production server
Lapo wrote:I'd expect SFS2X to be able to run inside the container without issues. At least until the container is running.
Is it not the case? If it does run, then I am not sure I fully understand what the problem is.
Can you clarify?
Yes, SFS2X will be running inside the container without any issue for as long as that SFS2X instance lifetime.
- For development, I used the sfs2x.sh script, the SFS2X instance run fine, until the instance crashes, or I decide to stop the docker container.
- For production, I used the sfs2x-service script, the SFS2X instance stopped right after the log "Starting sfs2x-service", so as the container
To be honest, I'm also a docker newbie here, but that's what I learned from using it.
I think the script that runs inside the docker container will send an exit signal to the container when it stops, to notify the docker to stop as well.
Anyway, maybe you haven't read my UPDATE, so I re-post it here:
willan wrote:I checked the sfs2x-service script code and found out about the start-launchd parameter
It's almost the same with start parameter, except it prints out logs and continue to run.
I tried that with docker and it works just fine.
So I wonder if I can use start-launchd parameter instead of start parameter for production?
Re: Using docker for production server
I think the script that runs inside the docker container will send an exit signal to the container when it stops, to notify the docker to stop as well.
Our start script doesn't do that. But maybe the difference using the start-launchd parameter is that it uses exec rather than nohup. Though it isn't really clear why nohup should behave differently in Docker. If that's the case. a lot of things are likely to break, since this is an often used mode of running background services.
Maybe this article is relevant?
https://unix.stackexchange.com/question ... ker-script
As regards your update I saw it, but I wanted to clear some basics before getting into more specific details:
So I wonder if I can use start-launchd parameter instead of start parameter for production?
Yes sure, it is probably the correct thing to do in that environment.
Meanwhile I have added a note in our TODO list to take a closer look at Docker and how to run SFS2X in it.
Let us know if you discover anything else, and happy holidays
Cheers
Re: Using docker for production server
Small addendum:
have you tried this? --> ./sfs2x-service run
It seems the same as launchd, but it's documented among the available commands, while the launchd command isn't, for some reason.
I say so because the sfs2x-service script is auto-generated by the installer software, Install4J.
Cheers
have you tried this? --> ./sfs2x-service run
It seems the same as launchd, but it's documented among the available commands, while the launchd command isn't, for some reason.
I say so because the sfs2x-service script is auto-generated by the installer software, Install4J.
Cheers
Re: Using docker for production server
Happy holidays
I haven't tried that, because I saw the 2 parameters use the different commands, so I didn't "dare" to try.
However, may I ask that is there any difference between start and run functions of install4j.com.smartfoxserver.v2.Main class, that used in the sfs2x-service script
Lapo wrote:Small addendum:
have you tried this? --> ./sfs2x-service run
It seems the same as launchd, but it's documented among the available commands, while the launchd command isn't, for some reason.
I say so because the sfs2x-service script is auto-generated by the installer software, Install4J.
Cheers
I haven't tried that, because I saw the 2 parameters use the different commands, so I didn't "dare" to try.
- start/start-launchd parameter runs with install4j.com.smartfoxserver.v2.Main start
- run parameter runs with install4j.com.smartfoxserver.v2.Main run
However, may I ask that is there any difference between start and run functions of install4j.com.smartfoxserver.v2.Main class, that used in the sfs2x-service script
Re: Using docker for production server
Hi,
unfortunately I can't tell for sure, as the whole launch system is auto-generated by the installation tool we use, which is Install4J.
What that does behind the scenes we don't know.
The only commands that are documented are the: start / stop / restart / status
The only suggestion I can give is to try the different command and see if they behave as expected.
Let us know.
unfortunately I can't tell for sure, as the whole launch system is auto-generated by the installation tool we use, which is Install4J.
What that does behind the scenes we don't know.
The only commands that are documented are the: start / stop / restart / status
The only suggestion I can give is to try the different command and see if they behave as expected.
Let us know.
Re: Using docker for production server
Yeah sure, I'm doing that
I will come back later with the result
Thanks a lot for your support
I will come back later with the result
Thanks a lot for your support
Re: Using docker for production server
Sorry to jump in but I use Docker for SFS2X and was unaware one shouldn't use sfs2x.sh in production because it works fine.
What I usually do is make a universal base image with the server itself, then extending that image in my projects and adding project-specific configurations and data. I also added an entrypoint script which allows other startup-scripts to be added into a directory to be executed on startup.
The base repository looks like this:
This is the Dockerfile. The runtime is based on OpenJDK's JRE version 11 but the installation of SFSX2X is performed in a plain Ubuntu 20.04. It also applies a patch file and any .patch files (I failed to report this, there is a small mistake in the log4j.properties):
The entrypoint.sh is just a usual entrypoint script:
@Lapo, the log4j patch is this:
Both the SFS2X files are the official, unmodified ones.
Building this image gives you a startable, unconfigured SFS2X 2.18.1 in a container.
Now, in order to use it in my project, I needed to save the configuration files. As I like having those in source control, I configured a blank SFS2X to my liking, then copied all the configuration files (core.xml, server.xml, Zone(s), ...) from the image to my project.
I can't go into all the details here but the Dockerfile installs maven into the OpenJDK 11 image, then builds my extension and custom storage JARs and a WAR for a push API I'm using, then copies everything on top of the SFS2X base image:
The envsubst_configs.sh file replaces ENV variables in given files - it is being copied into the entrypoint.sh.d/ directory created in the baseimage and will therefore be automatically run on container start, replacing several values in the config files ending in .envsubst with ENV vars:
This comes in handy in e.g. in the zone file:
...or the server config:
This way, the image is usable both in local development (using docker compose) and in production.
Sorry this became so long. I hope you can extract some useful information from the above.
Cheers,
Luke
What I usually do is make a universal base image with the server itself, then extending that image in my projects and adding project-specific configurations and data. I also added an entrypoint script which allows other startup-scripts to be added into a directory to be executed on startup.
The base repository looks like this:
Code: Select all
docker-entrypoint.sh
Dockerfile
log4j.properties.patch
SFS2X-Patch-2.18.1.zip
SFS2X_unix_2_18_0.tar.gz
This is the Dockerfile. The runtime is based on OpenJDK's JRE version 11 but the installation of SFSX2X is performed in a plain Ubuntu 20.04. It also applies a patch file and any .patch files (I failed to report this, there is a small mistake in the log4j.properties):
Code: Select all
FROM ubuntu:20.04 AS sfs2x
ARG SFS2X_BASE_TGZ=SFS2X_unix_2_18_0.tar.gz
ARG SFS2X_BASE_DIR=SmartFoxServer_2X
ARG SFS2X_PATCH_DIR=SFS2X-Patch-2.18.1
ARG SFS2X_PATCH_ZIP=${SFS2X_PATCH_DIR}.zip
WORKDIR /opt
COPY ["${SFS2X_BASE_TGZ}", "${SFS2X_PATCH_ZIP}", "*.patch", "./"]
RUN set -e \
&& apt-get update -y \
&& apt-get install -y --no-install-recommends unzip patch gettext-base \
&& tar -xzf "${SFS2X_BASE_TGZ}" \
&& cd "${SFS2X_BASE_DIR}" \
&& unzip ../"${SFS2X_PATCH_ZIP}" \
&& cd "${SFS2X_PATCH_DIR}" \
&& /bin/sh install-linux.sh \
&& cd .. \
&& rm -rf "${SFS2X_PATCH_DIR}" \
&& rm -rf jre \
&& cd .. \
&& for PATCH_FILE in *.patch; do \
echo applying ${PATCH_FILE}...; \
patch -p0 -i "${PATCH_FILE}"; \
done
FROM openjdk:11-jre
ENV FROM_SFS2X_DIR=/opt/SmartFoxServer_2X
ENV SFS2X_DIR=/home/sfs2x/SmartFoxServer_2X
ENV WORKDIR=${SFS2X_DIR}/SFS2X
RUN set -e \
&& addgroup sfs2x --gid 1001 \
&& adduser sfs2x --gecos "" --disabled-password --uid 1001 --ingroup sfs2x \
&& mkdir -p /docker-entrypoint.d \
&& chown sfs2x:sfs2x /docker-entrypoint.d \
&& apt-get update -y \
&& apt-get install -y --no-install-recommends gettext-base \
&& apt-get autoremove -y --purge \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --from=sfs2x --chown=sfs2x:sfs2x ["${FROM_SFS2X_DIR}", "${SFS2X_DIR}"]
COPY --chown=sfs2x:sfs2x ["docker-entrypoint.sh", "/"]
USER sfs2x
RUN set -xe \
&& ln -s "${JAVA_HOME}" "${SFS2X_DIR}/jre"
WORKDIR ${WORKDIR}
EXPOSE 8080 8443 9933/tcp 9933/udp
# java debugger and visualvm default ports
EXPOSE 8787 5000
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["bash", "sfs2x.sh"]
The entrypoint.sh is just a usual entrypoint script:
Code: Select all
#!/usr/bin/env bash
DIR=/docker-entrypoint.d
set -e
if [[ -d "$DIR" ]]; then
/bin/run-parts --verbose --exit-on-error --regex '.' "$DIR"
fi
exec "$@"
@Lapo, the log4j patch is this:
Code: Select all
--- SmartFoxServer_2X/SFS2X/config/log4j.properties 2021-01-06 23:36:25.000000000 +0100
+++ SmartFoxServer_2X/SFS2X/config/log4j.properties 2021-01-06 23:38:29.000000000 +0100
@@ -55,7 +55,7 @@
log4j.appender.bootFileAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.bootFileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.bootFileAppender.File=logs/boot/boot.log
-log4j.appender.bootConsoleAppender.threshold=DEBUG
+log4j.appender.bootFileAppender.threshold=DEBUG
log4j.appender.bootFileAppender.layout.ConversionPattern=%d{dd MMM yyyy | HH:mm:ss,SSS} | %-5p | %t | %c{3} | %3x | %m%n
log4j.appender.bootFileAppender.Encoding=UTF-8
Both the SFS2X files are the official, unmodified ones.
Building this image gives you a startable, unconfigured SFS2X 2.18.1 in a container.
Now, in order to use it in my project, I needed to save the configuration files. As I like having those in source control, I configured a blank SFS2X to my liking, then copied all the configuration files (core.xml, server.xml, Zone(s), ...) from the image to my project.
Code: Select all
> database-driver
mysql-connector-java-8.0.27.jar
postgresql-42.3.1.jar
> server
> config
core.xml.envsubst
log4j.properties
server.xml.envsubst
> docker-entrypoint.d
envsubst_configs.sh
> zones
Fishing Friends.zone.xml.envsubst
Dockerfile
I can't go into all the details here but the Dockerfile installs maven into the OpenJDK 11 image, then builds my extension and custom storage JARs and a WAR for a push API I'm using, then copies everything on top of the SFS2X base image:
Code: Select all
FROM openjdk:11 AS openjdk-maven
# maven build source:
# https://github.com/AdoptOpenJDK/openjdk-docker-build-tools/blob/master/11/maven/ubuntu/Dockerfile.hotspot.releases.full
ARG MAVEN_VERSION="3.8.4"
ARG USER_HOME_DIR="/root"
ARG MAVEN_SHA="a9b2d825eacf2e771ed5d6b0e01398589ac1bfa4171f36154d1b5787879605507802f699da6f7cfc80732a5282fd31b28e4cd6052338cbef0fa1358b48a5e3c8"
ARG MAVEN_BASE_URL="https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries"
ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "${USER_HOME_DIR}/.m2"
ENV USER_HOME_DIR ${USER_HOME_DIR}
RUN set -e \
&& mkdir -p "${MAVEN_HOME}" \
&& curl -LsSo /tmp/maven.tar.gz "${MAVEN_BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \
&& echo "${MAVEN_SHA} /tmp/maven.tar.gz" | sha512sum -c - \
&& tar -xzC "${MAVEN_HOME}" --strip-components=1 -f /tmp/maven.tar.gz \
&& rm -v /tmp/maven.tar.gz \
&& ln -s "${MAVEN_HOME}/bin/mvn" /usr/bin/mvn \
&& mvn -v
WORKDIR $USER_HOME_DIR
FROM openjdk-maven AS extension-build
COPY --from=registry.gitlab.com/robotriot/smartfoxserver-2x:2.18.1 /home/sfs2x/SmartFoxServer_2X/SFS2X/lib/sfs2x-core.jar /home/sfs2x/SmartFoxServer_2X/SFS2X/lib/sfs2x.jar ./
COPY custom-storage custom-storage
COPY zone-extension zone-extension
COPY push-api push-api
COPY pom.xml pom.xml
RUN set -e \
&& mvn clean package \
&& mkdir "${USER_HOME_DIR}/mvn-deps" \
&& mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory="${USER_HOME_DIR}/mvn-deps"
FROM registry.gitlab.com/robotriot/smartfoxserver-2x:2.18.1
RUN set -xe \
&& rm -rf www/HelloServlet \
&& rm -rf extensions/pyTest \
&& rm -rf zones/*
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/zone-extension/target/*.jar", "extensions/MyCustomZone/"]
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/push-api/target/*.war", "www/"]
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/custom-storage/target/*.jar", "extensions/__lib__/"]
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/mvn-deps/*.jar", "extensions/__lib__/"]
COPY --chown=sfs2x:sfs2x ["database-driver/*.jar", "extensions/__lib__/"]
COPY --chown=sfs2x:sfs2x ["server/config/*", "config/"]
COPY --chown=sfs2x:sfs2x ["server/zones/*", "zones/"]
COPY --chown=sfs2x:sfs2x ["server/docker-entrypoint.d/*", "/docker-entrypoint.d/"]
The envsubst_configs.sh file replaces ENV variables in given files - it is being copied into the entrypoint.sh.d/ directory created in the baseimage and will therefore be automatically run on container start, replacing several values in the config files ending in .envsubst with ENV vars:
Code: Select all
#!/usr/bin/env sh
set -e
echo "envsubst'ing config files..."
# find all files ending with .envsubst and feed them to envsubst command,
# overwriting the file without that extension in the same path.
# note: ArrayList is defined because $ArrayList is used in the zone file,
# getting picked up and replaced with nothing by envsubst. defining the
# "variable" we replace it with its exact string again.
ArrayList='$ArrayList' find "${WORKDIR}" -type f -a -name '*.envsubst' -exec sh -c 'echo "${1} > ${1%.envsubst}"; envsubst < "${1}" > "${1%.envsubst}"' _ {} \;
echo "done."
This comes in handy in e.g. in the zone file:
Code: Select all
<databaseManager active="true">
<driverName>org.postgresql.Driver</driverName>
<connectionString>jdbc:postgresql://${SFS2X_FF_DB_HOST}:${SFS2X_FF_DB_PORT}/${SFS2X_FF_DB_NAME}</connectionString>
<userName>${SFS2X_FF_DB_USERNAME}</userName>
<password>${SFS2X_FF_DB_PASSWORD}</password>
...
...or the server config:
Code: Select all
<adminUser>
<login>${SFS2X_ADMIN_USERNAME}</login>
<password>${SFS2X_ADMIN_PASSWORD}</password>
...
This way, the image is usable both in local development (using docker compose) and in production.
Sorry this became so long. I hope you can extract some useful information from the above.
Cheers,
Luke
Re: Using docker for production server
@Luke64, thanks for the detailed post
Re: Using docker for production server
This sounds like exactly what I want to do, using SFS2X in production on AWS ECS services. Might even use HAProxy on it...
How did you go about doing the licenses? Each instance needs it's own license to start, was there something you used to track and assign them?
How did you go about doing the licenses? Each instance needs it's own license to start, was there something you used to track and assign them?
Luke64 wrote:Sorry to jump in but I use Docker for SFS2X and was unaware one shouldn't use sfs2x.sh in production because it works fine.
What I usually do is make a universal base image with the server itself, then extending that image in my projects and adding project-specific configurations and data. I also added an entrypoint script which allows other startup-scripts to be added into a directory to be executed on startup.
The base repository looks like this:Code: Select all
docker-entrypoint.sh
Dockerfile
log4j.properties.patch
SFS2X-Patch-2.18.1.zip
SFS2X_unix_2_18_0.tar.gz
This is the Dockerfile. The runtime is based on OpenJDK's JRE version 11 but the installation of SFSX2X is performed in a plain Ubuntu 20.04. It also applies a patch file and any .patch files (I failed to report this, there is a small mistake in the log4j.properties):Code: Select all
FROM ubuntu:20.04 AS sfs2x
ARG SFS2X_BASE_TGZ=SFS2X_unix_2_18_0.tar.gz
ARG SFS2X_BASE_DIR=SmartFoxServer_2X
ARG SFS2X_PATCH_DIR=SFS2X-Patch-2.18.1
ARG SFS2X_PATCH_ZIP=${SFS2X_PATCH_DIR}.zip
WORKDIR /opt
COPY ["${SFS2X_BASE_TGZ}", "${SFS2X_PATCH_ZIP}", "*.patch", "./"]
RUN set -e \
&& apt-get update -y \
&& apt-get install -y --no-install-recommends unzip patch gettext-base \
&& tar -xzf "${SFS2X_BASE_TGZ}" \
&& cd "${SFS2X_BASE_DIR}" \
&& unzip ../"${SFS2X_PATCH_ZIP}" \
&& cd "${SFS2X_PATCH_DIR}" \
&& /bin/sh install-linux.sh \
&& cd .. \
&& rm -rf "${SFS2X_PATCH_DIR}" \
&& rm -rf jre \
&& cd .. \
&& for PATCH_FILE in *.patch; do \
echo applying ${PATCH_FILE}...; \
patch -p0 -i "${PATCH_FILE}"; \
done
FROM openjdk:11-jre
ENV FROM_SFS2X_DIR=/opt/SmartFoxServer_2X
ENV SFS2X_DIR=/home/sfs2x/SmartFoxServer_2X
ENV WORKDIR=${SFS2X_DIR}/SFS2X
RUN set -e \
&& addgroup sfs2x --gid 1001 \
&& adduser sfs2x --gecos "" --disabled-password --uid 1001 --ingroup sfs2x \
&& mkdir -p /docker-entrypoint.d \
&& chown sfs2x:sfs2x /docker-entrypoint.d \
&& apt-get update -y \
&& apt-get install -y --no-install-recommends gettext-base \
&& apt-get autoremove -y --purge \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --from=sfs2x --chown=sfs2x:sfs2x ["${FROM_SFS2X_DIR}", "${SFS2X_DIR}"]
COPY --chown=sfs2x:sfs2x ["docker-entrypoint.sh", "/"]
USER sfs2x
RUN set -xe \
&& ln -s "${JAVA_HOME}" "${SFS2X_DIR}/jre"
WORKDIR ${WORKDIR}
EXPOSE 8080 8443 9933/tcp 9933/udp
# java debugger and visualvm default ports
EXPOSE 8787 5000
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["bash", "sfs2x.sh"]
The entrypoint.sh is just a usual entrypoint script:Code: Select all
#!/usr/bin/env bash
DIR=/docker-entrypoint.d
set -e
if [[ -d "$DIR" ]]; then
/bin/run-parts --verbose --exit-on-error --regex '.' "$DIR"
fi
exec "$@"
@Lapo, the log4j patch is this:Code: Select all
--- SmartFoxServer_2X/SFS2X/config/log4j.properties 2021-01-06 23:36:25.000000000 +0100
+++ SmartFoxServer_2X/SFS2X/config/log4j.properties 2021-01-06 23:38:29.000000000 +0100
@@ -55,7 +55,7 @@
log4j.appender.bootFileAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.bootFileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.bootFileAppender.File=logs/boot/boot.log
-log4j.appender.bootConsoleAppender.threshold=DEBUG
+log4j.appender.bootFileAppender.threshold=DEBUG
log4j.appender.bootFileAppender.layout.ConversionPattern=%d{dd MMM yyyy | HH:mm:ss,SSS} | %-5p | %t | %c{3} | %3x | %m%n
log4j.appender.bootFileAppender.Encoding=UTF-8
Both the SFS2X files are the official, unmodified ones.
Building this image gives you a startable, unconfigured SFS2X 2.18.1 in a container.
Now, in order to use it in my project, I needed to save the configuration files. As I like having those in source control, I configured a blank SFS2X to my liking, then copied all the configuration files (core.xml, server.xml, Zone(s), ...) from the image to my project.Code: Select all
> database-driver
mysql-connector-java-8.0.27.jar
postgresql-42.3.1.jar
> server
> config
core.xml.envsubst
log4j.properties
server.xml.envsubst
> docker-entrypoint.d
envsubst_configs.sh
> zones
Fishing Friends.zone.xml.envsubst
Dockerfile
I can't go into all the details here but the Dockerfile installs maven into the OpenJDK 11 image, then builds my extension and custom storage JARs and a WAR for a push API I'm using, then copies everything on top of the SFS2X base image:Code: Select all
FROM openjdk:11 AS openjdk-maven
# maven build source:
# https://github.com/AdoptOpenJDK/openjdk-docker-build-tools/blob/master/11/maven/ubuntu/Dockerfile.hotspot.releases.full
ARG MAVEN_VERSION="3.8.4"
ARG USER_HOME_DIR="/root"
ARG MAVEN_SHA="a9b2d825eacf2e771ed5d6b0e01398589ac1bfa4171f36154d1b5787879605507802f699da6f7cfc80732a5282fd31b28e4cd6052338cbef0fa1358b48a5e3c8"
ARG MAVEN_BASE_URL="https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries"
ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "${USER_HOME_DIR}/.m2"
ENV USER_HOME_DIR ${USER_HOME_DIR}
RUN set -e \
&& mkdir -p "${MAVEN_HOME}" \
&& curl -LsSo /tmp/maven.tar.gz "${MAVEN_BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \
&& echo "${MAVEN_SHA} /tmp/maven.tar.gz" | sha512sum -c - \
&& tar -xzC "${MAVEN_HOME}" --strip-components=1 -f /tmp/maven.tar.gz \
&& rm -v /tmp/maven.tar.gz \
&& ln -s "${MAVEN_HOME}/bin/mvn" /usr/bin/mvn \
&& mvn -v
WORKDIR $USER_HOME_DIR
FROM openjdk-maven AS extension-build
COPY --from=registry.gitlab.com/robotriot/smartfoxserver-2x:2.18.1 /home/sfs2x/SmartFoxServer_2X/SFS2X/lib/sfs2x-core.jar /home/sfs2x/SmartFoxServer_2X/SFS2X/lib/sfs2x.jar ./
COPY custom-storage custom-storage
COPY zone-extension zone-extension
COPY push-api push-api
COPY pom.xml pom.xml
RUN set -e \
&& mvn clean package \
&& mkdir "${USER_HOME_DIR}/mvn-deps" \
&& mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory="${USER_HOME_DIR}/mvn-deps"
FROM registry.gitlab.com/robotriot/smartfoxserver-2x:2.18.1
RUN set -xe \
&& rm -rf www/HelloServlet \
&& rm -rf extensions/pyTest \
&& rm -rf zones/*
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/zone-extension/target/*.jar", "extensions/MyCustomZone/"]
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/push-api/target/*.war", "www/"]
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/custom-storage/target/*.jar", "extensions/__lib__/"]
COPY --chown=sfs2x:sfs2x --from=extension-build ["/root/mvn-deps/*.jar", "extensions/__lib__/"]
COPY --chown=sfs2x:sfs2x ["database-driver/*.jar", "extensions/__lib__/"]
COPY --chown=sfs2x:sfs2x ["server/config/*", "config/"]
COPY --chown=sfs2x:sfs2x ["server/zones/*", "zones/"]
COPY --chown=sfs2x:sfs2x ["server/docker-entrypoint.d/*", "/docker-entrypoint.d/"]
The envsubst_configs.sh file replaces ENV variables in given files - it is being copied into the entrypoint.sh.d/ directory created in the baseimage and will therefore be automatically run on container start, replacing several values in the config files ending in .envsubst with ENV vars:Code: Select all
#!/usr/bin/env sh
set -e
echo "envsubst'ing config files..."
# find all files ending with .envsubst and feed them to envsubst command,
# overwriting the file without that extension in the same path.
# note: ArrayList is defined because $ArrayList is used in the zone file,
# getting picked up and replaced with nothing by envsubst. defining the
# "variable" we replace it with its exact string again.
ArrayList='$ArrayList' find "${WORKDIR}" -type f -a -name '*.envsubst' -exec sh -c 'echo "${1} > ${1%.envsubst}"; envsubst < "${1}" > "${1%.envsubst}"' _ {} \;
echo "done."
This comes in handy in e.g. in the zone file:Code: Select all
<databaseManager active="true">
<driverName>org.postgresql.Driver</driverName>
<connectionString>jdbc:postgresql://${SFS2X_FF_DB_HOST}:${SFS2X_FF_DB_PORT}/${SFS2X_FF_DB_NAME}</connectionString>
<userName>${SFS2X_FF_DB_USERNAME}</userName>
<password>${SFS2X_FF_DB_PASSWORD}</password>
...
...or the server config:Code: Select all
<adminUser>
<login>${SFS2X_ADMIN_USERNAME}</login>
<password>${SFS2X_ADMIN_PASSWORD}</password>
...
This way, the image is usable both in local development (using docker compose) and in production.
Sorry this became so long. I hope you can extract some useful information from the above.
Cheers,
Luke
Re: Using docker for production server
luxmobile wrote:This sounds like exactly what I want to do, using SFS2X in production on AWS ECS services. Might even use HAProxy on it...
How did you go about doing the licenses? Each instance needs it's own license to start, was there something you used to track and assign them?
Currently I don't as we're still in development (launch in about 1 month) but I hope to be able to assign the licenses to the pods/containers through environment variables.
Sorry for coming back to you so late, did you eventually implement it? I'd like to know your findings going beyond what I wrote above
Cheers
Luke
Who is online
Users browsing this forum: No registered users and 52 guests