diff --git a/.docker/.env b/.docker/.env new file mode 100644 index 0000000..972e5a6 --- /dev/null +++ b/.docker/.env @@ -0,0 +1 @@ +export DGID=$(stat -c "%g" /var/run/docker.sock) diff --git a/.docker/docker-compose.server.yml b/.docker/docker-compose.server.yml new file mode 100644 index 0000000..578b290 --- /dev/null +++ b/.docker/docker-compose.server.yml @@ -0,0 +1,37 @@ +services: + server1: + build: + context: .. + dockerfile: .docker/server/Dockerfile + volumes: + - dockermc:/mcserver + environment: + - MC_SERVER=server1 + image: dockermc-server + networks: + default: + aliases: + - server1 + container_name: mc-server1 + server2: + build: + context: .. + dockerfile: .docker/server/Dockerfile + volumes: + - dockermc:/mcserver + environment: + - MC_SERVER=server2 + image: dockermc-server + networks: + default: + aliases: + - server2 + container_name: mc-server2 +volumes: + dockermc: + name: dockermc + driver: local + driver_opts: + type: none + o: bind + device: ../mcserver diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml index 7543a4f..3c251c8 100644 --- a/.docker/docker-compose.yml +++ b/.docker/docker-compose.yml @@ -4,13 +4,23 @@ services: context: .. dockerfile: .docker/runner/Dockerfile target: dev + args: + - DGID=${DGID} image: dockermc environment: - MC_VERSION=1.19 + - DGID=${DGID} volumes: - ../src:/src - server1: - build: - context: .. - dockerfile: .docker/server/Dockerfile - image: dockermc-server + - dockermc:/mcserver + - ./docker-compose.server.yml:/docker-compose.server.yml + - /var/run/docker.sock:/var/run/docker.sock + container_name: dockermc-runner +volumes: + dockermc: + name: dockermc + driver: local + driver_opts: + type: none + o: bind + device: ../mcserver diff --git a/.docker/runner/Dockerfile b/.docker/runner/Dockerfile index bc8b36e..9a8e6ae 100644 --- a/.docker/runner/Dockerfile +++ b/.docker/runner/Dockerfile @@ -1,6 +1,27 @@ FROM node:16 AS dev WORKDIR src +ARG DGID + +# Install Docker +RUN apt-get update +RUN apt-get install -y \ + ca-certificates \ + curl \ + gnupg \ + lsb-release +RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg +RUN echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \ + $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +RUN apt-get update +RUN apt-get install -y docker-ce docker-ce-cli containerd.io +# Install Docker Compose +RUN apt-get install -y docker-compose-plugin +# Add user to Docker group so Docker commands can be used +RUN groupadd -g $DGID hostDocker || : +RUN usermod -aG $DGID node +USER node ENTRYPOINT ["npm", "run", "start:watch"] diff --git a/.docker/server/Dockerfile b/.docker/server/Dockerfile index 033987d..574d8a6 100644 --- a/.docker/server/Dockerfile +++ b/.docker/server/Dockerfile @@ -1 +1,7 @@ FROM eclipse-temurin:17-jre-focal + +COPY .docker/server/start.sh ./ + +WORKDIR /mcserver + +ENTRYPOINT ["sh", "/start.sh"] diff --git a/.docker/server/start.sh b/.docker/server/start.sh new file mode 100644 index 0000000..5d0f30f --- /dev/null +++ b/.docker/server/start.sh @@ -0,0 +1,9 @@ +#for file in *.jar; do +# echo $file +#done +ls -la +file=$(ls *.jar | tail -1) +echo Starting $file +mkdir -p $MC_SERVER +cd $MC_SERVER +java -jar ../$file diff --git a/src/index.ts b/src/index.ts index c674291..3e51b85 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,41 @@ -console.log("Checking for server updates...", "MC", process.env.MC_VERSION); +import fetch from 'node-fetch'; +import { promises } from 'fs'; +import { exec } from 'child_process'; + +async function main() { + console.log("Checking for server updates...", "MC", process.env.MC_VERSION); + const res: { builds: Build[] } = await (await fetch(`https://api.papermc.io/v2/projects/paper/versions/${process.env.MC_VERSION}/builds`)).json() as any; + const lastBuild = res.builds[res.builds.length - 1]; + console.log("Latest build is", lastBuild.build, "at", new Date(Date.parse(lastBuild.time)).toLocaleString()) + try { + await promises.access('/mcserver/' + lastBuild.downloads.application.name) + } catch { + console.log("Build not found locally, downloading..."); + const newVerRes = await fetch(`https://api.papermc.io/v2/projects/paper/versions/${process.env.MC_VERSION}/builds/${lastBuild.build}/downloads/${lastBuild.downloads.application.name}`); + if (newVerRes.status > 299) { + console.log("Error while downloading", await newVerRes.json()); + throw new Error("Error while downloading"); + } else { + await promises.writeFile('/mcserver/' + lastBuild.downloads.application.name, newVerRes.body); + console.log("Build downloaded", lastBuild.downloads.application.name); + } + } + console.log("Starting server"); + exec('docker compose -f /docker-compose.server.yml up server1', function (error, stdout, stderr) { + if (stdout) { + console.log(stdout); + } + if (stderr) { + console.error(stderr); + } + if (error) { + console.error(error); + } + }); + +} + +// noinspection JSIgnoredPromiseFromCall +main(); + +type Build = { build: number, time: string, changes: { summary: string }[], downloads: { application: { name: string }, 'mojang-mappings': { name: string } } }; diff --git a/src/package-lock.json b/src/package-lock.json index d05c0f2..d767da8 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "docker-mc", "version": "1.0.0", + "dependencies": { + "node-fetch": "^3.2.6" + }, "devDependencies": { "@types/node": "^18.0.0", "source-map-support": "^0.5.21", @@ -49,6 +52,14 @@ "node": ">= 8" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "engines": { + "node": ">= 12" + } + }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -70,6 +81,39 @@ "through": "~2.3.1" } }, + "node_modules/fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/from": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", @@ -94,6 +138,41 @@ "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.6.tgz", + "integrity": "sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -250,6 +329,14 @@ "node": ">=4.2.0" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -296,6 +383,11 @@ "which": "^2.0.1" } }, + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" + }, "duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -317,6 +409,23 @@ "through": "~2.3.1" } }, + "fetch-blob": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.5.tgz", + "integrity": "sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, "from": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", @@ -341,6 +450,21 @@ "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", "dev": true }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.6.tgz", + "integrity": "sha512-LAy/HZnLADOVkVPubaxHDft29booGglPFDr2Hw0J1AercRh01UiVFm++KMDnJeH9sHgNB4hsXPii7Sgym/sTbw==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -454,6 +578,11 @@ "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/src/package.json b/src/package.json index 3d216bf..df06288 100644 --- a/src/package.json +++ b/src/package.json @@ -4,6 +4,7 @@ "description": "", "main": "dist/index.js", "types": "dist/index.d.ts", + "type": "module", "directories": { "test": "test" }, @@ -23,5 +24,8 @@ "source-map-support": "^0.5.21", "tsc-watch": "^5.0.3", "typescript": "^4.7.4" + }, + "dependencies": { + "node-fetch": "^3.2.6" } } diff --git a/src/tsconfig.json b/src/tsconfig.json index 5a313de..49f1dbe 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -1,7 +1,8 @@ { "compilerOptions": { "outDir": "dist", - "rootDir": "." + "rootDir": ".", + "moduleResolution": "Node" }, - "include": ["."] + "include": ["."], }