Configuration files are automatically generated based on env variables in the Docker image

This commit is contained in:
Exynox 2024-06-02 21:45:51 +03:00
parent 6d65fae7e4
commit 170be95dc5
8 changed files with 104 additions and 15 deletions

View File

@ -29,7 +29,7 @@ RUN cd build && make -j $(nproc)
FROM ubuntu:22.04 as app
WORKDIR /app
RUN apt-get update && apt-get install -y python2 libdevil-dev libbsd-dev && apt-get clean
RUN apt-get update && apt-get install -y gettext python2 libdevil-dev libbsd-dev && apt-get clean
# Copy the binaries from the build stage
COPY --from=build /app/build/src/db/db /bin/db
@ -39,6 +39,9 @@ COPY --from=build /app/build/src/quest/qc /bin/qc
# Copy the game files
COPY ./gamefiles/ .
# Copy the auxiliary files
COPY ./docker/ .
# Compile the quests
RUN cd /app/data/quest && python2 make.py
@ -48,3 +51,9 @@ RUN ln -s ./conf/item_names_en.txt item_names.txt
RUN ln -s ./conf/item_proto.txt item_proto.txt
RUN ln -s ./conf/mob_names_en.txt mob_names.txt
RUN ln -s ./conf/mob_proto.txt mob_proto.txt
# Set up default environment variables
ENV PUBLIC_BIND_IP 0.0.0.0
ENV INTERNAL_BIND_IP 0.0.0.0
ENTRYPOINT ["/usr/bin/bash", "docker-entrypoint.sh"]

View File

@ -35,7 +35,7 @@ Also install DevIL (1.7.8) and the BSD compatibility library:
apt-get install -y libdevil-dev libbsd-dev
```
Install `vcpkg` according to the [lastest instructions](https://vcpkg.io/en/getting-started.html).
Install `vcpkg` according to the [latest instructions](https://vcpkg.io/en/getting-started.html).
Build and install the required libraries:
```shell
@ -79,7 +79,7 @@ goodies you wish. Also, a lot of time.
- Removed unused functionalities (time bombs, activation servers, other Korean stuff)
- Switched to the [effolkronium/random PRNG](https://github.com/effolkronium/random) instead of the standard C functions.
- Refactored macros to modern C++ functions.
- Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `CONFIG` file. (Might need further work)
- Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `game.conf` file. (Might need further work)
- Refactored logging to use [spdlog](https://github.com/gabime/spdlog) for more consistent function calls.
- Refactored login code to use Argon2ID.
@ -102,7 +102,7 @@ This is a very serious security risk and one of the reasons this project is stil
- Fixed buffer overruns and integer overflows in SQL queries.
## 5. Further plans
- Migrate `conf.txt` and `CONFIG` to a modern dotenv-like format, which would enable pretty nice Docker images.
- Migrate `db.conf` and `game.conf` to a modern dotenv-like format, which would enable pretty nice Docker images.
- Add a health check to the Docker image.
- Use the [fmt](https://fmt.dev/latest/index.html) library for safe and modern string formatting.
- Handle kernel signals (SIGTERM, SIGHUP etc.) for gracefully shutting down the game server.

18
docker/conf/db.conf.tmpl Normal file
View File

@ -0,0 +1,18 @@
WELCOME_MSG = "DB Server has been started"
SQL_ACCOUNT = "${MYSQL_HOST} ${MYSQL_DB_ACCOUNT} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}"
SQL_COMMON = "${MYSQL_HOST} ${MYSQL_DB_COMMON} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}"
SQL_PLAYER = "${MYSQL_HOST} ${MYSQL_DB_PLAYER} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}"
TABLE_POSTFIX = ""
BIND_PORT = ${DB_PORT}
DB_SLEEP_MSEC = 10
CLIENT_HEART_FPS = 10
HASH_PLAYER_LIFE_SEC = 600
BACKUP_LIMIT_SEC = 3600
PLAYER_ID_START = 100
PLAYER_DELETE_LEVEL_LIMIT = 70
ITEM_ID_RANGE = 10000001 20000000
TEST_SERVER = ${TEST_SERVER}

View File

@ -0,0 +1,41 @@
HOSTNAME: ${GAME_HOSTNAME}
CHANNEL: ${GAME_CHANNEL}
PUBLIC_IP: ${PUBLIC_IP}
PUBLIC_BIND_IP: ${PUBLIC_BIND_IP}
INTERNAL_IP: ${INTERNAL_IP}
INTERNAL_BIND_IP: ${INTERNAL_BIND_IP}
PORT: ${GAME_PORT}
P2P_PORT: ${GAME_P2P_PORT}
DB_ADDR: ${DB_ADDR}
DB_PORT: ${DB_PORT}
COMMON_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_COMMON} ${MYSQL_PORT}
LOG_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_LOG} ${MYSQL_PORT}
PLAYER_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_PLAYER} ${MYSQL_PORT}
TABLE_POSTFIX:
AUTH_SERVER: ${GAME_AUTH_SERVER}
MARK_SERVER: ${GAME_MARK_SERVER}
MAP_ALLOW: ${GAME_MAP_ALLOW}
MAX_LEVEL: ${GAME_MAX_LEVEL}
PK_PROTECT_LEVEL: 15
SPAM_BLOCK_MAX_LEVEL: 90
GOLD_DROP_LIMIT_TIME: 10
MALL_URL: ${GAME_MALL_URL}
CHECK_MULTIHACK: 0
SPEEDHACK_LIMIT_COUNT: 300
SPEEDHACK_LIMIT_BONUS: 80
ADMINPAGE_IP: 127.0.0.1
ADMINPAGE_PASSWORD: metin2adminpass
PASSES_PER_SEC: 25
SAVE_EVENT_SECOND_CYCLE: 180
PING_EVENT_SECOND_CYCLE: 180
VIEW_RANGE: 8000
TEST_SERVER: ${TEST_SERVER}

View File

@ -0,0 +1,9 @@
#!/bin/sh
# docker-entrypoint.sh
# Generate configuration files based on environment variables
envsubst <"/app/conf/db.conf.tmpl" >"/app/db.conf"
envsubst <"/app/conf/game.conf.tmpl" >"/app/game.conf"
# Run the standard container command.
exec "$@"

View File

@ -46,7 +46,7 @@ Mysql-Funktion der neuesten Generation.
--]]
mysql_query = function(query)
if not pre then
local rt = io.open('CONFIG','r'):read('*all')
local rt = io.open('game.conf','r'):read('*all')
pre,_= string.gsub(rt,'.+PLAYER_SQL:%s(%S+)%s(%S+)%s(%S+)%s(%S+).+','-h%1 -u%2 -p%3 -D%4')
end
math.randomseed(os.time())

View File

@ -126,9 +126,9 @@ void emptybeat(LPHEART heart, int pulse)
//
int Start()
{
if (!CConfig::instance().LoadFile("conf.txt"))
if (!CConfig::instance().LoadFile("db.conf"))
{
SPDLOG_ERROR("Loading conf.txt failed.");
SPDLOG_ERROR("Loading db.conf failed.");
return false;
}

View File

@ -292,7 +292,7 @@ void config_init(const string& st_localeServiceName)
string st_configFileName;
st_configFileName.reserve(32);
st_configFileName = "CONFIG";
st_configFileName = "game.conf";
if (!st_localeServiceName.empty())
{
@ -775,19 +775,27 @@ void config_init(const string& st_localeServiceName)
TOKEN("test_server")
{
printf("-----------------------------------------------\n");
printf("TEST_SERVER\n");
printf("-----------------------------------------------\n");
str_to_number(test_server, value_string);
if (test_server) {
printf("-----------------------------------------------\n");
printf("TEST_SERVER\n");
printf("-----------------------------------------------\n");
}
continue;
}
TOKEN("speed_server")
{
printf("-----------------------------------------------\n");
printf("SPEED_SERVER\n");
printf("-----------------------------------------------\n");
str_to_number(speed_server, value_string);
if (speed_server) {
printf("-----------------------------------------------\n");
printf("SPEED_SERVER\n");
printf("-----------------------------------------------\n");
}
continue;
}
#ifdef __AUCTION__
@ -887,7 +895,11 @@ void config_init(const string& st_localeServiceName)
two_arguments(value_string, szIP, sizeof(szIP), szPort, sizeof(szPort));
if (!*szIP || (!*szPort && strcasecmp(szIP, "master")))
// Skip if arguments are empty
if (!*szIP)
continue;
if (!*szPort && strcasecmp(szIP, "master"))
{
SPDLOG_CRITICAL("AUTH_SERVER: syntax error: <ip|master> <port>");
exit(EXIT_FAILURE);