ryansheehan/terraria

TShock StorageType mysql doesn't work with mono-slim

treytabner opened this issue · 6 comments

If you set StorageType to mysql and configure a valid mysql connection, TShock fails to start with an error. I believe this is due to the change to using mono-slim instead of the full mono image. After reviewing the upstream mono Dockerfile to see which additional packages were installed, I installed fsharp and TShock with StorageType mysql now worked fine.

Error logs from before fsharp was installed:

2021-04-27 23:07:29 - TShock: INFO: TShock was improperly shut down. Please use the exit command in the future to prevent this.
2021-04-27 23:07:29 - TShock: ERROR: Fatal Startup Exception
2021-04-27 23:07:29 - TShock: ERROR: System.Exception: Fatal TShock initialization exception: failed to connect to MySQL database. See inner exception for details. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
  at System.Reflection.RuntimePropertyInfo.GetterAdapterFrame[T,R] (System.Reflection.RuntimePropertyInfo+Getter`2[T,R] getter, System.Object obj) [0x00000] in <c453bf849bb84e719dbec0475e99db95>:0
  at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x0006c] in <c453bf849bb84e719dbec0475e99db95>:0
   --- End of inner exception stack trace ---
  at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x00080] in <c453bf849bb84e719dbec0475e99db95>:0
  at MySql.Data.MySqlClient.NativeDriver.SetConnectAttrs () [0x0006b] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.Authentication.MySqlAuthenticationPlugin.Authenticate (System.Boolean reset) [0x00081] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.NativeDriver.Authenticate (System.String authMethod, System.Boolean reset) [0x0002a] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.NativeDriver.Open () [0x00317] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.Driver.Open () [0x0000b] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.Driver.Create (MySql.Data.MySqlClient.MySqlConnectionStringBuilder settings) [0x0004d] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection () [0x00000] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection () [0x0008a] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver () [0x00042] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.GetConnection () [0x0001c] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlConnection.Open () [0x0016c] in <15029c3817b245ffb50e9433f5ade25d>:0
  at TShockAPI.DB.DbExt.QueryReader (System.Data.IDbConnection olddb, System.String query, System.Object[] args) [0x00007] in <73c23d07dcdb43d98198c69a51aba79c>:0
   --- End of inner exception stack trace ---
  at TShockAPI.DB.DbExt.QueryReader (System.Data.IDbConnection olddb, System.String query, System.Object[] args) [0x0006b] in <73c23d07dcdb43d98198c69a51aba79c>:0
  at TShockAPI.DB.SqlTableCreator.GetColumns (TShockAPI.DB.SqlTable table) [0x00093] in <73c23d07dcdb43d98198c69a51aba79c>:0
  at TShockAPI.DB.SqlTableCreator.EnsureTableStructure (TShockAPI.DB.SqlTable table) [0x0000d] in <73c23d07dcdb43d98198c69a51aba79c>:0
  at TShockAPI.DB.BanManager..ctor (System.Data.IDbConnection db) [0x000e7] in <73c23d07dcdb43d98198c69a51aba79c>:0
  at TShockAPI.TShock.Initialize () [0x003f4] in <73c23d07dcdb43d98198c69a51aba79c>:0

I had the same roadblock and tested using the mono-devel package and it started working normally, the tshock docs clearly states:
"TShock requires the mono-complete package.
(...)
Some users have experienced issues with these instructions too. If your server won't let players join, install mono-devel."
https://tshock.readme.io/docs

Currently using the mono-slim is saving about 150Mb, for some people it might be important, but I am not sure if this is the only error due to not respecting the TShock documentation.

I believe the best approach would be to use mono instead of mono-slim. But if it is really important for the maintainer another tag could be created e.g. tshock-slim.

I just removed the -slim from the base image. Let me know if it works better.

docker pull ryshe/terraria:tshock-1.4.2.3-4.5.5-2

Unfortunately, it takes some time for the image to be able to connect with an external database, and that breaks the server. To be able to fix that I had to change the bootstrap script to wait while the database is unreachable.

To test the connection to the database it is needed to get the server address from the config.json, due to that I had to add jq and mariadb-client packages.

Since I prefer to go on the safer side of things I updated the mono and alpine versions and installed the mono-devel package, but those three changes I believe can be ignored.

I am not sure if I should submit these changes or how to do it here.

These are the files and changes I did in my test environment, the lines outside the code blocks are from the original files to indicate where to place the changes:

Boostrap.sh

cp -Rfv /plugins/* ./ServerPlugins

STORAGETYPE=$(cat $CONFIGPATH/config.json | jq -r '.StorageType')
if [ $STORAGETYPE = "mysql" ]; then
  DATABASE_SERVER=$(cat $CONFIGPATH/config.json | jq -r '.MySqlHost' | cut -f1 -d':')
  DATABASE_PORT=$(cat $CONFIGPATH/config.json | jq -r '.MySqlHost' | cut -f2 -d':')
  DATABASE_USER_NAME=$(cat $CONFIGPATH/config.json | jq -r '.MySqlUsername')
  DATABASE_USER_PASSWORD=$(cat $CONFIGPATH/config.json | jq -r '.MySqlPassword')
  echo "Waiting for the database server."
  while ! mysql -h$DATABASE_SERVER -P$DATABASE_PORT -u$DATABASE_USER_NAME -p$DATABASE_USER_PASSWORD  -e ";" ; do
    sleep 0.1;
  done
fi

WORLD_PATH="/root/.local/share/Terraria/Worlds/$WORLD_FILENAME"

Dockerfile

FROM alpine:3.14.1 AS base

RUN apk add --update-cache \

(...)
chmod +x /tshock/bootstrap.sh

FROM mono:6.12.0.107

LABEL maintainer="Ryan Sheehan rsheehan@gmail.com"

(...)

RUN apt-get update -y && \

    apt-get install -y nuget mono-devel mariadb-client jq && \

rm -rf /var/lib/apt/lists/* /tmp/*


Perhaps someone more versed in shell script and docker might be able to propose better changes to fix this delay between the bootstrap.sh script being run and the database server becoming reachable without the extra packages?

Anyway, with these changes I could integrate with the database server with no problems.

I just opened the pull request:
#81

I just removed the -slim from the base image. Let me know if it works better.

docker pull ryshe/terraria:tshock-1.4.2.3-4.5.5-2

I'm trying to set up a server with mysql database storage using ryshe/terraria:tshock-1.4.3.6-4.5.17-2 and I'm still getting the same exception message raised by @treytabner:

Bootstrap:
world_file_name=main.wld
configpath=/root/.local/share/Terraria/Worlds
logpath=/tshock/logs

Copying plugins...
cp: cannot stat '/plugins/*': No such file or directory
Environment WORLD_FILENAME specified
Loading to world main.wld...
Error Logging Enabled.
TerrariaAPI Version: 2.1.0.0 (Protocol v1.4.3.6 (248), OTAPI 1.4.3.6)
[TShock] Info Config path has been set to /root/.local/share/Terraria/Worlds
[TShock] Info Log path has been set to /tshock/logs
TShock was improperly shut down. Please use the exit command in the future to prevent this.
Fatal Startup Exception
System.Exception: Fatal TShock initialization exception: failed to connect to MySQL database. See inner exception for details.
---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.IO.FileNotFoundException: Could not load file or assembly 'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
  at System.Reflection.RuntimePropertyInfo.GetterAdapterFrame[T,R] (System.Reflection.RuntimePropertyInfo+Getter`2[T,R] getter, System.Object obj) [0x00000] in <533173d24dae460899d2b10975534bb0>:0
  at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x0006c] in <533173d24dae460899d2b10975534bb0>:0
   --- End of inner exception stack trace ---
  at System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[] index) [0x00080] in <533173d24dae460899d2b10975534bb0>:0
  at MySql.Data.MySqlClient.NativeDriver.SetConnectAttrs () [0x0006b] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.Authentication.MySqlAuthenticationPlugin.Authenticate (System.Boolean reset) [0x00081] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.NativeDriver.Authenticate (System.String authMethod, System.Boolean reset) [0x0002a] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.NativeDriver.Open () [0x00317] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.Driver.Open () [0x0000b] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.Driver.Create (MySql.Data.MySqlClient.MySqlConnectionStringBuilder settings) [0x0004d] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection () [0x00000] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection () [0x0008a] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver () [0x00042] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlPool.GetConnection () [0x0001c] in <15029c3817b245ffb50e9433f5ade25d>:0
  at MySql.Data.MySqlClient.MySqlConnection.Open () [0x0016c] in <15029c3817b245ffb50e9433f5ade25d>:0
  at TShockAPI.DB.DbExt.QueryReader (System.Data.IDbConnection olddb, System.String query, System.Object[] args) [0x00007] in <a320748a76594c1fac9736170a0aea47>:0
   --- End of inner exception stack trace ---
  at TShockAPI.DB.DbExt.QueryReader (System.Data.IDbConnection olddb, System.String query, System.Object[] args) [0x0006b] in <a320748a76594c1fac9736170a0aea47>:0
  at TShockAPI.DB.SqlTableCreator.GetColumns (TShockAPI.DB.SqlTable table) [0x00093] in <a320748a76594c1fac9736170a0aea47>:0
  at TShockAPI.DB.SqlTableCreator.EnsureTableStructure (TShockAPI.DB.SqlTable table) [0x0000d] in <a320748a76594c1fac9736170a0aea47>:0
  at TShockAPI.DB.BanManager..ctor (System.Data.IDbConnection db) [0x000e7] in <a320748a76594c1fac9736170a0aea47>:0
  at TShockAPI.TShock.Initialize () [0x00405] in <a320748a76594c1fac9736170a0aea47>:0
Stream closed EOF for games/terraria-776767ccb4-xgfjh (terraria)