This commit is contained in:
Andrew 2022-03-02 18:35:58 -05:00
commit 6bc5e5b51f
10 changed files with 123 additions and 47 deletions

View File

@ -10,6 +10,10 @@ docker-compose.yml
.gitlab-ci.yml .gitlab-ci.yml
# root # root
.editorconfig
.pylintrc
.venv
.vscode
crafty_commander.exe crafty_commander.exe
DBCHANGES.md DBCHANGES.md
docker-compose.yml.example docker-compose.yml.example

View File

@ -7,18 +7,43 @@ LABEL maintainer="Dockerfile created by Zedifus <https://gitlab.com/zedifus>"
# Security Patch for CVE-2021-44228 # Security Patch for CVE-2021-44228
ENV LOG4J_FORMAT_MSG_NO_LOOKUPS=true ENV LOG4J_FORMAT_MSG_NO_LOOKUPS=true
# Install Packages And Dependencies # Create non-root user & required dirs
COPY requirements.txt /commander/requirements.txt RUN useradd -M crafty \
RUN apt update \ && mkdir /commander \
&& apt install -y gcc python3 python3-pip libmariadb-dev openjdk-8-jre-headless openjdk-11-jre-headless openjdk-16-jre-headless openjdk-17-jre-headless default-jre \ && chown -R crafty:root /commander
&& pip3 install --no-cache-dir -r /commander/requirements.txt
# Copy Source & copy default config from image # Install required system packages
COPY ./ /commander RUN apt-get update \
&& apt-get -y --no-install-recommends install \
gcc \
python3 \
python3-dev \
python3-pip \
python3-venv \
libmariadb-dev \
default-jre \
openjdk-8-jre-headless \
openjdk-11-jre-headless \
openjdk-16-jre-headless \
openjdk-17-jre-headless \
&& apt-get autoremove \
&& apt-get clean
# Switch to service user for installing crafty deps
USER crafty
WORKDIR /commander WORKDIR /commander
COPY --chown=crafty:root requirements.txt ./
RUN python3 -m venv ./.venv \
&& . .venv/bin/activate \
&& pip3 install --no-cache-dir --upgrade setuptools==50.3.2 pip==22.0.3 \
&& pip3 install --no-cache-dir -r requirements.txt \
&& deactivate
# Copy Source w/ perms & prepare default config from example
COPY --chown=crafty:root ./ ./
RUN mv ./app/config ./app/config_original \ RUN mv ./app/config ./app/config_original \
&& mv ./app/config_original/default.json.example ./app/config_original/default.json \ && mv ./app/config_original/default.json.example ./app/config_original/default.json \
&& chmod +x ./docker_launcher.sh && chmod +x ./docker_launcher.sh
# Expose Web Interface port & Server port range # Expose Web Interface port & Server port range
EXPOSE 8000 EXPOSE 8000

View File

@ -8,7 +8,7 @@ a web interface for the server administrators to interact with their servers. Cr
is compatible with Docker, Linux, Windows 7, Windows 8 and Windows 10. is compatible with Docker, Linux, Windows 7, Windows 8 and Windows 10.
## Documentation ## Documentation
Temporary documentation available on [GitLab](https://gitlab.com/crafty-controller/crafty-commander/wikis/home) Documentation available on [wiki.craftycontrol.com](https://craftycontrol.com)
## Meta ## Meta
Project Homepage - https://craftycontrol.com Project Homepage - https://craftycontrol.com
@ -17,15 +17,38 @@ Discord Server - https://discord.gg/9VJPhCE
Git Repository - https://gitlab.com/crafty-controller/crafty-web Git Repository - https://gitlab.com/crafty-controller/crafty-web
## Basic Docker Usage <br>
**To get started with docker**, all you need to do is pull the image from this git repository's registry. ## Basic Docker Usage 🐳
This is done by using `docker-compose` or `docker run`(You don't need to clone the Repository and build, like in 3.x ).
If you have a config folder already from previous local installation or docker setup, the image should mount this volume, if none is present then it will populate its own config folder for you. With `Crafty Controller 4.0` we have focused on building our DevOps Principles, implementing build automation, and securing our containers, with the hopes of making our Container user's lives abit easier.
### Using the registry image: ### - Two big changes you will notice is:
The provided image supports both `arm64` and `amd64` out the box, if you have issues though you can build it yourself. - We now provide pre-built images for you guys.
- Containers now run as non-root, using practices used by OpenSwift & Kubernetes (root group perms).
> __**⚠ 🔻WARNING: [WSL/WSL2 | WINDOWS 11 | DOCKER DESKTOP]🔻**__ <br>
BE ADVISED! Upstream is currently broken for Minecraft running on **Docker under WSL/WSL2, Windows 11 / DOCKER DESKTOP!** <br>
On '**Stop**' or '**Restart**' of the MC Server, there is a 90% chance the World's Chunks will be shredded irreparably! <br>
Please only run Docker on Linux, If you are using Windows we have a portable installs found here: [Latest-Stable](https://gitlab.com/crafty-controller/crafty-commander/-/jobs/artifacts/master/download?job=win-prod-build), [Latest-Development](https://gitlab.com/crafty-controller/crafty-commander/-/jobs/artifacts/dev/download?job=win-dev-build)
----
### - To get started with docker 🛫
All you need to do is pull the image from this git repository's registry.
This is done by using `'docker-compose'` or `'docker run'` (You don't need to clone the Repository and build, like in 3.x ).
If you have a config folder already from previous local installation or _docker setup_*, the image should mount this volume, if no config present then it will populate its own config folder for you. <br> <br>
As the Dockerfile uses the permission structure of `crafty:root` **internally** there is no need to worry about matching the `UID` or `GID` on the host system :)
> ***Make sure the ownership permissions on `servers/ backups/ logs/ configs/ imports/` in the `docker/` are not `root:root`, please just chown the dir recursively to your host user.**
> **Please make sure if you are using a `compose` file, that the above volume mount directories are present, otherwise, docker will just make them and they'll be `root:root` which is not what we want.💀**
<br>
### - Using the registry image 🌎
The provided image supports both `arm64` and `amd64` out the box, if you have issues though you can build it yourself with the `compose` file in `docker/`.
The image is located at: `registry.gitlab.com/crafty-controller/crafty-commander:latest` The image is located at: `registry.gitlab.com/crafty-controller/crafty-commander:latest`
| Branch | Status | | Branch | Status |
@ -50,13 +73,20 @@ or
```bash ```bash
$ echo <token> | docker login registry.gitlab.com -u <username> --password-stdin $ echo <token> | docker login registry.gitlab.com -u <username> --password-stdin
``` ```
or or
```bash ```bash
$ cat ~/my_password.txt | docker login registry.gitlab.com -u <username> --password-stdin $ cat ~/my_password.txt | docker login registry.gitlab.com -u <username> --password-stdin
``` ```
Then use one of the following methods: Then use one of the following methods:
#### docker-compose.yml ### **docker-compose.yml:**
```sh
# We need to make them because of permissions remember!
$ mkdir docker/ docker/backups docker/logs docker/servers docker/config docker/import
# Make your compose file
$ vim docker-compose.yml
```
```yml ```yml
version: '3' version: '3'
@ -64,40 +94,52 @@ services:
crafty: crafty:
container_name: crafty_commander container_name: crafty_commander
image: registry.gitlab.com/crafty-controller/crafty-commander:latest image: registry.gitlab.com/crafty-controller/crafty-commander:latest
environment:
- TZ=Etc/UTC
ports: ports:
- "8000:8000" # HTTP - "8000:8000" # HTTP
- "8443:8443" # HTTPS - "8443:8443" # HTTPS
- "8123:8123" # DYNMAP - "8123:8123" # DYNMAP
- "19132:19132/udp" # BEDROCK - "19132:19132/udp" # BEDROCK
- "24000-25600:24000-25600" # MC SERV PORT RANGE - "25500-25600:25500-25600" # MC SERV PORT RANGE
volumes: volumes:
- ./docker/backups:/commander/backups - ./docker/backups:/commander/backups
- ./docker/logs:/commander/logs - ./docker/logs:/commander/logs
- ./docker/servers:/commander/servers - ./docker/servers:/commander/servers
- ./docker/config:/commander/app/config - ./docker/config:/commander/app/config
- ./docker/import:/commander/import
``` ```
#### docker run
```sh ```sh
$ docker-compose up -d && docker-compose logs -f
```
<br>
### **docker run:**
```sh
# We need to make them because of permissions remember!
$ mkdir docker/ docker/backups docker/logs docker/servers docker/config docker/import
$ docker run \ $ docker run \
--name crafty_commander \ --name crafty_commander \
-p 8000:8000 \ -p 8000:8000 \
-p 8443:8443 \ -p 8443:8443 \
-p 8123:8123 \ -p 8123:8123 \
-p 19132:19132/udp \ -p 19132:19132/udp \
-p 24000-25600:24000-25600 \ -p 25500-25600:25500-25600 \
-e TZ=Etc/UTC \
-v "/$(pwd)/docker/backups:/commander/backups" \ -v "/$(pwd)/docker/backups:/commander/backups" \
-v "/$(pwd)/docker/logs:/commander/logs" \ -v "/$(pwd)/docker/logs:/commander/logs" \
-v "/$(pwd)/docker/servers:/commander/servers" \ -v "/$(pwd)/docker/servers:/commander/servers" \
-v "/$(pwd)/docker/config:/commander/app/config" \ -v "/$(pwd)/docker/config:/commander/app/config" \
-v "/$(pwd)/docker/import:/commander/import" \
registry.gitlab.com/crafty-controller/crafty-commander:latest registry.gitlab.com/crafty-controller/crafty-commander:latest
``` ```
### Building from the cloned repository: ### **Building from the cloned repository:**
If you are building from `docker-compose` you can find the compose file in `./docker/docker-compose.yml` just `cd` to the docker directory and `docker-compose up -d` If you are building from `docker-compose` you can find the compose file in `./docker/docker-compose.yml` just `cd` to the docker directory and `docker-compose up -d`
If you'd rather not use `docker-compose` you can use the following `docker run`in the directory where the *Dockerfile* is: If you'd rather not use `docker-compose` you can use the following `docker run` in the directory where the *Dockerfile* is:
```sh ```sh
# REMEMBER, Build your image first! # REMEMBER, Build your image first!
$ docker build . -t crafty $ docker build . -t crafty
@ -108,11 +150,13 @@ $ docker run \
-p 8443:8443 \ -p 8443:8443 \
-p 8123:8123 \ -p 8123:8123 \
-p 19132:19132/udp \ -p 19132:19132/udp \
-p 24000-25600:24000-25600 \ -p 25500-25600:25500-25600 \
-e TZ=Etc/UTC \
-v "/$(pwd)/docker/backups:/commander/backups" \ -v "/$(pwd)/docker/backups:/commander/backups" \
-v "/$(pwd)/docker/logs:/commander/logs" \ -v "/$(pwd)/docker/logs:/commander/logs" \
-v "/$(pwd)/docker/servers:/commander/servers" \ -v "/$(pwd)/docker/servers:/commander/servers" \
-v "/$(pwd)/docker/config:/commander/app/config" \ -v "/$(pwd)/docker/config:/commander/app/config" \
-v "/$(pwd)/docker/import:/commander/import" \
crafty crafty
``` ```
A fresh build will take several minutes depending on your system, but will be rapid there after. A fresh build will take several minutes depending on your system, but will be rapid thereafter.

View File

@ -451,7 +451,7 @@ class Controller:
server_log_file, server_stop, port, server_type='minecraft-bedrock') server_log_file, server_stop, port, server_type='minecraft-bedrock')
if os.name != "nt": if os.name != "nt":
if helper.check_file_exists(full_jar_path): if helper.check_file_exists(full_jar_path):
os.chmod(full_jar_path, 2775) os.chmod(full_jar_path, 0o2775)
return new_id return new_id
def import_bedrock_zip_server(self, server_name: str, zip_path: str, server_exe: str, port: int): def import_bedrock_zip_server(self, server_name: str, zip_path: str, server_exe: str, port: int):
@ -500,7 +500,7 @@ class Controller:
server_log_file, server_stop, port, server_type='minecraft-bedrock') server_log_file, server_stop, port, server_type='minecraft-bedrock')
if os.name != "nt": if os.name != "nt":
if helper.check_file_exists(full_jar_path): if helper.check_file_exists(full_jar_path):
os.chmod(full_jar_path, 2775) os.chmod(full_jar_path, 0o2775)
return new_id return new_id

View File

@ -4,15 +4,17 @@ services:
crafty: crafty:
container_name: crafty_commander container_name: crafty_commander
image: registry.gitlab.com/crafty-controller/crafty-commander:latest image: registry.gitlab.com/crafty-controller/crafty-commander:latest
environment:
- TZ=Etc/UTC
ports: ports:
- "8000:8000" # HTTP - "8000:8000" # HTTP
- "8443:8443" # HTTPS - "8443:8443" # HTTPS
- "8123:8123" # DYNMAP - "8123:8123" # DYNMAP
- "19132:19132/udp" # BEDROCK - "19132:19132/udp" # BEDROCK
- "24000-25600:24000-25600" # MC SERV PORT RANGE - "25500-25600:25500-25600" # MC SERV PORT RANGE
volumes: volumes:
- ./docker/backups:/commander/backups - ./docker/backups:/commander/backups
- ./docker/logs:/commander/logs - ./docker/logs:/commander/logs
- ./docker/servers:/commander/servers - ./docker/servers:/commander/servers
- ./docker/config:/commander/app/config - ./docker/config:/commander/app/config
- ./import:/commander/import - ./docker/import:/commander/import

0
docker/config/.gitkeep Normal file
View File

View File

@ -4,12 +4,14 @@ services:
crafty: crafty:
container_name: crafty_commander container_name: crafty_commander
build: .. build: ..
environment:
- TZ=Etc/UTC
ports: ports:
- "8000:8000" # HTTP - "8000:8000" # HTTP
- "8443:8443" # HTTPS - "8443:8443" # HTTPS
- "8123:8123" # DYNMAP - "8123:8123" # DYNMAP
- "19132:19132/udp" # BEDROCK - "19132:19132/udp" # BEDROCK
- "24000-25600:24000-25600" # MC SERV PORT RANGE - "25500-25600:25500-25600" # MC SERV PORT RANGE
volumes: volumes:
- ./backups:/commander/backups - ./backups:/commander/backups
- ./logs:/commander/logs - ./logs:/commander/logs

0
docker/import/.gitkeep Normal file
View File

View File

@ -1,9 +1,11 @@
#!/bin/sh #!/bin/sh
# Check if config exists from existing installation (venv or previous docker launch) # Check if config exists from existing installation (venv or previous docker launch)
if [ ! "$(ls -A ./app/config)" ]; then if [ ! "$(ls -A --ignore=.gitkeep ./app/config)" ]; then
mkdir ./app/config/ mkdir ./app/config/
cp -r ./app/config_original/* ./app/config/ cp -r ./app/config_original/* ./app/config/
fi fi
# Activate our prepared venv and launch crafty with provided args
. .venv/bin/activate
exec python3 main.py $@ exec python3 main.py $@

27
main.py
View File

@ -7,14 +7,11 @@ import logging.config
import signal import signal
from app.classes.shared.console import console from app.classes.shared.console import console
from app.classes.shared.helpers import helper from app.classes.shared.helpers import helper
if helper.check_file_exists('/.dockerenv'): if helper.checkRoot():
console.cyan("Docker environment detected!") console.critical("Root detected. Root/Admin access denied. Run Crafty again with non-elevated permissions.")
else: time.sleep(5)
if helper.checkRoot(): console.critical("Crafty shutting down. Root/Admin access denied.")
console.critical("Root detected. Root/Admin access denied. Run Crafty again with non-elevated permissions.") sys.exit(0)
time.sleep(5)
console.critical("Crafty shutting down. Root/Admin access denied.")
sys.exit(0)
# pylint: disable=wrong-import-position # pylint: disable=wrong-import-position
from app.classes.shared.main_models import installer, database from app.classes.shared.main_models import installer, database
from app.classes.shared.tasks import TasksManager from app.classes.shared.tasks import TasksManager
@ -152,10 +149,10 @@ if __name__ == '__main__':
controller.set_project_root(project_root) controller.set_project_root(project_root)
controller.clear_unexecuted_commands() controller.clear_unexecuted_commands()
def sigterm_handler(): def sigterm_handler(*sig):
print() # for newline print() # for newline
logger.info("Recieved SIGTERM, stopping Crafty") logger.info(f"Recieved SIGINT [{sig[0]}], stopping Crafty...")
console.info("Recieved SIGTERM, stopping Crafty") console.info(f"Recieved SIGINT [{sig[0]}], stopping Crafty...")
tasks_manager._main_graceful_exit() tasks_manager._main_graceful_exit()
Crafty.universal_exit() Crafty.universal_exit()
@ -166,8 +163,8 @@ if __name__ == '__main__':
Crafty.cmdloop() Crafty.cmdloop()
except KeyboardInterrupt: except KeyboardInterrupt:
print() # for newline print() # for newline
logger.info("Recieved SIGINT, stopping Crafty") logger.info("Recieved SIGINT, stopping Crafty...")
console.info("Recieved SIGINT, stopping Crafty") console.info("Recieved SIGINT, stopping Crafty...")
tasks_manager._main_graceful_exit() tasks_manager._main_graceful_exit()
Crafty.universal_exit() Crafty.universal_exit()
else: else:
@ -178,8 +175,8 @@ if __name__ == '__main__':
break break
time.sleep(1) time.sleep(1)
except KeyboardInterrupt: except KeyboardInterrupt:
logger.info("Recieved SIGINT, stopping Crafty") logger.info("Recieved SIGINT, stopping Crafty...")
console.info("Recieved SIGINT, stopping Crafty") console.info("Recieved SIGINT, stopping Crafty...")
break break
tasks_manager._main_graceful_exit() tasks_manager._main_graceful_exit()
Crafty.universal_exit() Crafty.universal_exit()