Added multistage, configs, and shrunk size

This commit is contained in:
FrozenFOXX
2020-05-25 20:42:56 -07:00
parent 40cc523b61
commit 2f6a9f8181
7 changed files with 538 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
# Base image
FROM ubuntu:20.04
# Builder image
FROM ubuntu:20.04 AS builder
# Variables
ENV CRAWL_REPO="https://github.com/crawl/crawl.git" \
@@ -11,34 +11,61 @@ ENV CRAWL_REPO="https://github.com/crawl/crawl.git" \
libsdl2-dev libfreetype6-dev libpng-dev ttf-dejavu-core advancecomp pngcrush" \
DEBIAN_FRONTEND=noninteractive
# Logic
# Install packages for the build
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y ${BUILD_DEPS} ${APP_DEPS}
# Install Tornado
RUN pip3 install tornado
# Retrieve crawl
RUN git clone ${CRAWL_REPO} /src/
# Build crawl
RUN cd /src/crawl-ref/source && \
make -j4 USE_DGAMELAUNCH=y WEBTILES=y
make install -j4 DESTDIR=/app/ USE_DGAMELAUNCH=y WEBTILES=y
# Make directory for RCs
RUN mkdir -p /src/crawl-ref/source/rcs
# Set up webserver components
RUN cp -r /src/crawl-ref/source/webserver /app/ && \
cp -r /src/crawl-ref/source/util /app/
# Clean up unnecessary packages
RUN apt-get remove -y ${BUILD_DEPS} && \
apt-get autoremove --purge -y && \
rm -rf /var/lib/apt/lists/*
# Runtime image
FROM ubuntu:20.04
# Environment Variables
ENV APP_DEPS="bzip2 liblua5.1-0-dev python3-minimal python3-pip python3-yaml \
python-is-python3 ncurses-term locales-all sqlite3 libpcre3 locales \
lsof sudo libbot-basicbot-perl" \
DATA_DIR=/data \
DEBIAN_FRONTEND=noninteractive
# Install packages for the runtime
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y ${APP_DEPS}
# Install Tornado
RUN pip3 install tornado
# Copy over the compiled files
COPY --from=builder /app/ /app/
# Copy over custom configs
COPY settings/init.txt /app/settings/
COPY util/webtiles-init-player.sh /app/util/
COPY webserver/config.py /app/webserver/
COPY webserver/games.d/* /app/webserver/games.d/
# Adjustments for the container
RUN mkdir -p /data/rcs && \
mkdir -p /data/webserver
# Clean up unnecessary package lists
RUN rm -rf /var/lib/apt/lists/*
# Expose ports
EXPOSE 8080
# Set the WORKDIR
WORKDIR /src/crawl-ref/source
WORKDIR /app
# Launch WebTiles server
CMD [ "./webserver/server.py" ]

View File

@@ -1,5 +1,5 @@
# Base image
FROM ubuntu:20.04
# Builder image
FROM ubuntu:20.04 AS builder
# Variables
ENV CRAWL_REPO="https://github.com/crawl/crawl.git" \
@@ -11,34 +11,61 @@ ENV CRAWL_REPO="https://github.com/crawl/crawl.git" \
libsdl2-dev libfreetype6-dev libpng-dev ttf-dejavu-core advancecomp pngcrush" \
DEBIAN_FRONTEND=noninteractive
# Logic
# Install packages for the build
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y ${BUILD_DEPS} ${APP_DEPS}
# Install Tornado
RUN pip3 install tornado
# Retrieve crawl
RUN git clone ${CRAWL_REPO} /src/
# Build crawl
RUN cd /src/crawl-ref/source && \
make -j4 USE_DGAMELAUNCH=y WEBTILES=y
make install -j4 DESTDIR=/app/ USE_DGAMELAUNCH=y WEBTILES=y
# Make directory for RCs
RUN mkdir -p /src/crawl-ref/source/rcs
# Set up webserver components
RUN cp -r /src/crawl-ref/source/webserver /app/ && \
cp -r /src/crawl-ref/source/util /app/
# Clean up unnecessary packages
RUN apt-get remove -y ${BUILD_DEPS} && \
apt-get autoremove --purge -y && \
rm -rf /var/lib/apt/lists/*
# Runtime image
FROM ubuntu:20.04
# Environment Variables
ENV APP_DEPS="bzip2 liblua5.1-0-dev python3-minimal python3-pip python3-yaml \
python-is-python3 ncurses-term locales-all sqlite3 libpcre3 locales \
lsof sudo libbot-basicbot-perl" \
DATA_DIR=/data \
DEBIAN_FRONTEND=noninteractive
# Install packages for the runtime
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y ${APP_DEPS}
# Install Tornado
RUN pip3 install tornado
# Copy over the compiled files
COPY --from=builder /app/ /app/
# Copy over custom configs
COPY settings/init.txt /app/settings/
COPY util/webtiles-init-player.sh /app/util/
COPY webserver/config.py /app/webserver/
COPY webserver/games.d/* /app/webserver/games.d/
# Adjustments for the container
RUN mkdir -p /data/rcs && \
mkdir -p /data/webserver
# Clean up unnecessary package lists
RUN rm -rf /var/lib/apt/lists/*
# Expose ports
EXPOSE 8080
# Set the WORKDIR
WORKDIR /src/crawl-ref/source
WORKDIR /app
# Launch WebTiles server
CMD [ "./webserver/server.py" ]

View File

@@ -20,4 +20,18 @@ The following will run the latest Webtiles crawl server.
```
docker run -d --rm -p 8080:8080 --name=crawl_webtiles frozenfoxx/crawl:latest
```
```
## Persistent Deployment
All player RCs and webserver database files are located within `/data` within the container. Bind mount a host directory to this location to maintain persistence.
```
docker run \
-d \
--rm \
-v /data:/data \
-p 8080:8080 \
--name=crawl_webtiles \
frozenfoxx/crawl:latest
```

87
settings/init.txt Normal file
View File

@@ -0,0 +1,87 @@
##### Crawl Init file ###############################################
# For descriptions of all options, as well as some more in-depth information
# on setting them, consult the file
# options_guide.txt
# in your /docs directory. If you can't find it, the file is also available
# online at:
# https://github.com/crawl/crawl/blob/master/crawl-ref/docs/options_guide.txt
#
# Crawl uses the first file of the following list as its option file:
# * init.txt in the -rcdir directory (if specified)
# * .crawlrc in the -rcdir directory (if specified)
# * init.txt (in the Crawl directory)
# * ~/.crawl/init.txt (Unix only)
# * ~/.crawlrc (Unix only)
# * ~/init.txt (Unix only)
# * settings/init.txt (in the Crawl directory)
##### Some basic explanation of option syntax #######################
# Lines beginning with '#' are comments. The basic syntax is:
#
# field = value or field.subfield = value
#
# Only one specification is allowed per line.
#
# The terms are typically case-insensitive except in the fairly obvious
# cases (the character's name and specifying files or directories when
# on a system that has case-sensitive filenames).
#
# White space is stripped from the beginning and end of the line, as
# well as immediately before and after the '='. If the option allows
# multiple comma/semicolon-separated terms (such as
# autopickup_exceptions), all whitespace around the separator is also
# trimmed. All other whitespace is left intact.
#
# There are three broad types of Crawl options: true/false values (booleans),
# arbitrary values, and lists of values. The first two types use only the
# simple =, with later options - which includes your options that are different
# from the defaults - overriding earlier ones. List options allow using +=, ^=,
# -=, and = to append, prepend, remove, and reset, respectively. Usually you will
# want to use += to add to a list option. Lastly, there is := which you can use
# to create an alias, like so:
# ae := autopickup_exceptions
# From there on, 'ae' will be treated as if it you typed autopickup_exceptions,
# so you can save time typing it.
#
##### Other files ###################################################
# You can include other files from your options file using the 'include'
# option. Crawl will treat it as if you copied the whole text of that file
# into your options file in that spot. You can uncomment some of the following
# lines by removing the beginning '#' to include some of the other files in
# this folder.
# Some useful, more advanced options, implemented in LUA.
# include = advanced_optioneering.txt
# Alternative vi bindings for Dvorak users.
# include = dvorak_command_keys.txt
# Alternative vi bindings for Colemak users.
# include = colemak_command_keys.txt
# Alternative vi bindings for Neo users.
# include = neo_command_keys.txt
# Override the vi movement keys with a non-command.
# include = no_vi_command_keys.txt
# Turn the shift-vi keys into safe move, instead of run.
# include = safe_move_shift.txt
##### Ancient versions ##############################################
# If you're used to the interface of ancient versions of Crawl, you may
# get back parts of it by uncommenting the following options:
# include = 034_command_keys.txt
# And to revert monster glyph and colouring changes:
# include = 052_monster_glyphs.txt
# include = 060_monster_glyphs.txt
# include = 071_monster_glyphs.txt
# include = 080_monster_glyphs.txt
# include = 0.9_monster_glyphs.txt
# include = 0.12_monster_glyphs.txt
# include = 0.13_monster_glyphs.txt
# include = 0.14_monster_glyphs.txt

View File

@@ -0,0 +1,15 @@
#!/bin/sh
RCDIR=/data/rcs/
INPROGRESSDIR=/data/rcs/running
TTYRECDIR=/data/rcs/ttyrecs/$1
DEFAULT_RC=/app/settings/init.txt
PLAYERNAME=$1
mkdir -p $RCDIR
mkdir -p $INPROGRESSDIR
mkdir -p $TTYRECDIR
if [ ! -f ${RCDIR}/${PLAYERNAME}.rc ]; then
cp ${DEFAULT_RC} ${RCDIR}/${PLAYERNAME}.rc
fi

212
webserver/config.py Normal file
View File

@@ -0,0 +1,212 @@
# Warning! Servers will not update or merge with the version controlled copy of
# this file, so any parameters here, and code that uses them, need to come
# without the assumption that they will be present in any given config.py on a
# server. Furthermore, on a typical rebuild in a production server, a running
# webtiles server *will not restart*, so you can't even assume that any config-
# specific code that you've added will be consistently present. This
# particularly impacts templated html files, which are loaded and called
# dynamically, so *do* get updated immediately on a rebuild. If something like
# client.html raises an exception, this will trigger 500 errors across the whole
# server.
#
# One useful workaround for all this is to get config paramters with the builtin
# `getattr` function: e.g. `getattr(config, "dgl_mode", False) will safely get
# this variable from the module, defaulting to False if it doesn't exist (and
# not raising an exception). `hasattr` is also safe.
import logging
import os
import yaml
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict # type: ignore
dgl_mode = True
bind_nonsecure = True # Set to false to only use SSL
bind_address = ""
bind_port = 8080
# Or listen on multiple address/port pairs (overriding the above) with:
# bind_pairs = (
# ("127.0.0.1", 8080),
# ("localhost", 8082),
# ("", 8180), # All addresses
# )
logging_config = {
# "filename": "webtiles.log",
"level": logging.INFO,
"format": "%(asctime)s %(levelname)s: %(message)s"
}
password_db = "/data/webserver/passwd.db3"
# Uncomment and change if you want this db somewhere separate from the
# password_db location.
settings_db = "/data/webserver/user_settings.db3"
static_path = "./webserver/static"
template_path = "./webserver/templates/"
# Path for server-side unix sockets (to be used to communicate with crawl)
server_socket_path = None # Uses global temp dir
# Server name, so far only used in the ttyrec metadata
server_id = ""
# Disable caching of game data files
game_data_no_cache = True
# Watch socket dirs for games not started by the server
watch_socket_dirs = False
use_game_yaml = True
# Game configs
#
# You can define game configs in two ways:
# 1. With a static dictionary `games`
# 2. As extra games to append to this list from `load_games.load_games` (which
# by default loads games as defined in `games.d/*.yaml`).
#
# All options in this config are documented in games.d/base.yaml.
games = OrderedDict([
("dcss-web-trunk", dict(
name = "Play trunk",
crawl_binary = "/app/bin/crawl",
rcfile_path = "/data/rcs/",
macro_path = "/data/rcs/",
morgue_path = "/data/rcs/%n",
inprogress_path = "/data/rcs/running",
ttyrec_path = "/data/rcs/ttyrecs/%n",
socket_path = "/data/rcs",
client_path = "/app/webserver/game_data/",
# dir_path = ".",
# cwd = ".",
morgue_url = None,
show_save_info = True,
milestone_path = "/data/rcs/milestones",
send_json_options = True,
# env = {"LANG": "en_US.UTF8"},
)),
])
dgl_status_file = "/data/rcs/status"
# Extra paths to tail for milestone updates. This is a legacy setting, you
# should use `milestone_path` or `dir_path` for each game in the games dict.
# (This setting can be a string or list of strings.)
milestone_file = ["./milestones"]
status_file_update_rate = 5
recording_term_size = (80, 24)
max_connections = 100
# Script to initialize a user, e.g. make sure the paths
# and the rc file exist. This is not done by the server
# at the moment.
init_player_program = "./util/webtiles-init-player.sh"
ssl_options = None # No SSL
#ssl_options = {
# "certfile": "./webserver/localhost.crt",
# "keyfile": "./webserver/localhost.key"
#}
ssl_address = ""
ssl_port = 8081
# Or listen on multiple address/port pairs (overriding the above) with:
# ssl_bind_pairs = (
# ("127.0.0.1", 8081),
# ("localhost", 8083),
# )
connection_timeout = 600
max_idle_time = 5 * 60 * 60
use_gzip = True
# Seconds until stale HTTP connections are closed
# This needs a patch currently not in mainline tornado.
http_connection_timeout = None
# Set this to true if you are behind a reverse proxy
# Your proxy must set header X-Real-IP
#
# Enabling this option when webtiles is NOT protected behind a reverse proxy
# introduces a security risk. An attacker could inject a false address into the
# X-Real-IP header. Do not enable this option if the webtiles server is
# directly exposed to users.
http_xheaders = None
kill_timeout = 10 # Seconds until crawl is killed after HUP is sent
nick_regex = r"^[a-zA-Z0-9]{3,20}$"
max_passwd_length = 20
allow_password_reset = False # Set to true to allow users to request a password reset email. Some settings must be properly configured for this to work
# Set to the primary URL where a player would reach the main lobby
# For example: "http://crawl.akrasiac.org/"
# This is required for for password reset, as it will be the base URL for
# recovery URLs.
lobby_url = None
# Proper SMTP settings are required for password reset to function properly.
# if smtp_host is anything other than `localhost`, you may need to adjust the
# timeout settings (see server.py, calls to ioloop.set_blocking_log_threshold).
# TODO: set_blocking_log_threshold is deprecated in tornado 5+...
# Ideally, test out these settings carefully in a non-production setting
# before enabling this, as there's a bunch of ways for this to go wrong and you
# don't want to get your SMTP server blacklisted.
smtp_host = "localhost"
smtp_port = 25
smtp_use_ssl = False
smtp_user = "" # set to None for no auth
smtp_password = ""
smtp_from_addr = "noreply@crawl.example.org" # The address from which automated
# emails will be sent
# crypt() algorithm, e.g. "1" for MD5 or "6" for SHA-512; see crypt(3). If
# false, use traditional DES (but then only the first eight characters of the
# password are significant). If set to "broken", use traditional DES with
# the password itself as the salt; this is necessary for compatibility with
# dgamelaunch, but should be avoided if possible because it leaks the first
# two characters of the password's plaintext.
crypt_algorithm = "broken"
# The length of the salt string to use. If crypt_algorithm is false, this
# setting is ignored and the salt is two characters.
crypt_salt_length = 16
login_token_lifetime = 7 # Days
uid = None # If this is not None, the server will setuid to that (numeric) id
gid = None # after binding its sockets.
umask = None # e.g. 0077
chroot = None
pidfile = None
daemon = False # If true, the server will detach from the session after startup
# Set to a URL with %s where lowercased player name should go in order to
# hyperlink WebTiles spectator names to their player pages.
# For example: "http://crawl.akrasiac.org/scoring/players/%s.html"
# Set to None to disable player page hyperlinks
player_url = None
# Only for development:
# This is insecure; do not set development_mode = True in production!
development_mode = False
# Disable caching of static files which are not part of game data.
no_cache = development_mode
# Automatically log in all users with the username given here.
autologin = None

127
webserver/games.d/base.yaml Normal file
View File

@@ -0,0 +1,127 @@
# Games are stored in order. The order of games you define in these files will
# be preserved, and the files will be loaded in sorted order.
# %n in paths and urls is replaced by the current username.
games:
# id must be unique for each game
- id: seeded-web-trunk
# The name for this game, displayed on the webtiles HTML interface
name: Custom seed
# Games are called with the following argv:
# [
# $crawl_binary,
# *$pre_options,
# "-name", "%n",
# "-rc", "$rcfile_path/%n.rc",
# "-macro", "$macro_path/%n.macro",
# "-morgue", "$morgue_path,"
# *$options,
# "-dir", "$dir_path"
# "-webtiles-socket", "$socket_path/%n:$timestamp.sock",
# "-await-connection"
# ]
# Relative to the server's CWD
crawl_binary: /app/bin/crawl
# rcfile_path, macro_path, morgue_path, and socket_path, and dir_path use
# server's CWD for relative paths, unless your crawl_binary command changes
# the CWD (like dgamelaunch-config's crawl-*-launcher.sh scripts do).
rcfile_path: /data/rcs/
macro_path: /data/rcs/
morgue_path: /data/rcs/%n
# Sockets are placed in this directory and used for communication between./webserver
# the webtiles server and DCSS executable. If you change the CWD with a
# crawl_binary script, this path will have to be absolute (so both the
# server and DCSS can find it).
socket_path: /data/rcs
# # The DCSS "dir" is where save games plus logfile/milestones files are
# # written. If you don't specify this, the game uses a compile-time default,
# # which depends on your OS and compilation settings.
# dir_path: .
# Directory where ttyrec files for active games are written to.
# Relative to the server's CWD.
inprogress_path: /data/rcs/running
# Directory where ttyrec files are stored for the individual user.
# Relative to the server's CWD.
ttyrec_path: /data/rcs/ttyrecs/%n
# Static content used by the game (eg spritesheets, game HTML). DCSS builds
# this as the web/ directory.
# Relative to the server's CWD.
client_path: /app/webserver/game_data/
# # The working directory to run crawl from. You shouldn't really need to set
# # this, unless you are trying to run the circa 2016 fork DCSS Circus Animals
# # on a real webtiles server, and dont want save games littering your
# # webserver directory.
# # NOTE: if you set this, all settings which are documented as "relative to
# # the server's CWD" will become relative to the path here instead. This path
# # itself is relative to the server's CWD, though.
# cwd: .
# The URL shown to users when they create a character dump (`#`) ingame. You
# can use %n in it, like a directory. If you don't specify one, the user
# isn't told where their dump was written -- but it's still written.
morgue_url: None
# # The path to the game's "milestones" file. If you specify dir_path this can
# # be inferred automatically (since it's $dir_path/milestones), but otherwise
# # you should specify this explicitly. The milestones file is read to
# # populate the 'milestones' column in the HTML interface. If you don't
# # specify a milestones path, you'll just see nothing specified there.
# # (Note: DCSS writes both "milestones" and "milestones-seeded", we'll
# # automatically pick up both if you specify the former's path.)
# milestone_path: ./rcs/milestones
# # Array of extra options to add to the start of the DCSS command. Prefer
# # using 'options' unless the ordering is critical.
# pre_options: []
# Array of extra options to add to the DCSS command.
options:
- -seed
# # Map of extra environment variables to set when executing the DCSS command.
# # All env vars from the webtiles server environment are automatically
# # inherited.
# env:
# LANG: en_US.UTF8
# show_save_info: set to True if the binary supports save info json
# and you want it to be queried each time the player enters the lobby.
# (With a lot of binaries, it isn't necessarily recommended yet to blanket
# enable this, as it can slow down a player's lobby loading.)
show_save_info: True
# send_json_options is a legacy option. Always include this set to 'true'.
# (Or submit a PR to remove it.)
send_json_options: True
- id: tut-web-trunk
name: Tutorial
crawl_binary: /app/bin/crawl
rcfile_path: /data/rcs/
macro_path: /data/rcs/
morgue_path: /data/rcs/%n
inprogress_path: /data/rcs/running
ttyrec_path: /data/rcs/ttyrecs/%n
socket_path: /data/rcs
client_path: /app/webserver/game_data/
# dir_path: .
# cwd: .
morgue_url: None
# milestone_path: ./rcs/milestones
show_save_info: True
send_json_options: True
options:
- -tutorial
# env:
# LANG: en_US.UTF8
- id: sprint-web-trunk
name: Sprint
crawl_binary: /app/bin/crawl
rcfile_path: /data/rcs/
macro_path: /data/rcs/
morgue_path: /data/rcs/%n
inprogress_path: /data/rcs/running
ttyrec_path: /data/rcs/ttyrecs/%n
socket_path: /data/rcs
client_path: /app/webserver/game_data/
# dir_path: .
# cwd: .
morgue_url: None
# milestone_path: ./rcs/milestones
show_save_info: True
send_json_options: True
options:
- -sprint
# env:
# LANG: en_US.UTF8