Spring Boot na BiedaHostingu
Wstęp: Po co to robimy?
BiedaHosting to hosting współdzielony - nie VPS, nie serwer dedykowany. Mimo to da się na nim uruchomić aplikację Spring Boot. Największy problem? Standardowe JRE waży za dużo na hosting z limitem 250 MB.
Rozwiązanie: używamy jlink żeby zbudować minimalne JRE tylko z modułami których potrzebuje nasza aplikacja. Efekt? JRE schodzi do 60 MB, a całość z fat JARem mieści się w 100 MB.
Czego potrzebujesz:
- Konto na BiedaHostingu (pakiet bieda25 - 250 MB miejsca)
- Open JDK 21 zainstalowane lokalnie (do budowania)
- Maven lub Gradle
- Dostęp SSH do serwera
Ważna uwaga: To środowisko testowe - nie do produkcji. Aplikacje Java na hostingu współdzielonym mogą być ubijane przez system przy wysokim zużyciu zasobów. Dlatego w tym wpisie omawiamy też watchdoga który automatycznie restartuje aplikację.
Krok 1 - Budowanie aplikacji Spring Boot
Zbuduj aplikację lokalnie do pliku JAR:
mvn clean package -DskipTests
Gotowy plik JAR znajdziesz w folderze target/.
Przykładowa nazwa: test-app-1.0-SNAPSHOT.jar Ten poradnik skupia się na architekturze wdrożeniowej, a nie na pisaniu samego kodu biznesowego.
Krok 2 - Budowanie minimalnego JRE przez jlink
Zamiast wysyłać pełne JRE na serwer , budujemy minimalne tylko z modułami których potrzebuje nasza aplikacja Spring Boot.
Najpierw sprawdź jakich modułów potrzebuje Twoja aplikacja:
jdeps --ignore-missing-deps \
--print-module-deps \
target/test-app-1.0-SNAPSHOT.jar
Czasami jdeps może mieć problem z zajrzeniem do środka fat jara. Dlatego rozpakuj go do temp_folder i wydaj zmodyfikowaną komendę:
jdeps --ignore-missing-deps --multi-release 21 --print-module-deps -recursive temp_folder/BOOT-INF/classes temp_folder/BOOT-INF/lib/*.jar
Polecenie wylistuje wszystkie potrzebne moduły. Dla typowej aplikacji Spring Boot wynik będzie podobny do:
java.base,java.sql,java.naming,java.desktop,java.management,
java.security.jgss,java.instrument,java.rmi,jdk.unsupported
Teraz zbuduj minimalne JRE:
jlink \
--add-modules java.base,java.sql,java.naming,java.desktop,\
java.management,java.security.jgss,java.instrument,java.rmi,jdk.unsupported \
--strip-debug \
--no-header-files \
--no-man-pages \
--compress=zip-9 \
--output custom-runtime
Jeżeli pracujesz na windows a chcesz przygotowac jre dla linuxa - pobierz jdk 21 dla linux w tar.gz i rozpakuj w dowolnym folderze. Wydaj komende zmodyfikowaną o ścieżke do modułów
jlink --module-path JDK_LINUX_HOME\jmods --add-modules java.base,java.compiler,java.desktop,java.instrument,java.management,java.naming,java.net.http,java.prefs,java.rmi,java.scripting,java.security.jgss,java.sql,jdk.jfr,jdk.unsupported --output jre-linux-mini --strip-debug --no-man-pages --no-header-files --compress=2
Sprawdź rozmiar:
Wynik: około 60 MB
Uwaga: Moduły zależą od tego co używa Twoja aplikacja.
Bardziej rozbudowane aplikacje mogą potrzebować więcej modułów -
użyj jdeps żeby sprawdzić co jest naprawdę potrzebne.
Krok 3 - Wgrywanie na biedahosting
Wgraj na przez FTP lub panel hostingu na serwer dwa elementy:
- Folder
custom-runtime/- minimalne JRE - Plik JAR - np.
test-app-1.0-SNAPSHOT.jar
Docelowa struktura na serwerze:
/home/twojlogin/java/testapp/
├── custom-runtime/
│ └── bin/
│ └── java
└── test-app-1.0-SNAPSHOT.jar
Krok 4 - Uruchomienie aplikacji przez SSH
Zaloguj się przez SSH i utwórz potrzebne foldery:
mkdir -p $HOME/tmp
mkdir -p $HOME/tomcat
Uruchom aplikację przez tmux używając własnego JRE:
tmux new-session -d -s testapp \
"$HOME/java/testapp/custom-runtime/bin/java \
-Djava.io.tmpdir=$HOME/tmp \
-jar $HOME/java/testapp/test-app-1.0-SNAPSHOT.jar \
--server.port=18080 \
--server.address=127.0.0.1 \
--server.tomcat.basedir=$HOME/tomcat \
>> $HOME/java/testapp/app.log 2>&1"
Kilka ważnych parametrów:
custom-runtime/bin/java- używamy własnego minimalnego JRE-Djava.io.tmpdir=$HOME/tmp- katalog tymczasowy w folderze użytkownika--server.address=127.0.0.1- aplikacja słucha tylko lokalnie--server.tomcat.basedir=$HOME/tomcat- katalog roboczy Tomcata--server.port=18080- port aplikacji. Wybierze swoje porty!
⚠ Ważna uwaga bezpieczeństwa: Aplikacja nasłuchuje na 127.0.0.1 -
czyli tylko lokalnie, nie jest bezpośrednio dostępna z internetu. Jeżeli nie ustawisz tego parametru - każdy w interncie moze dostac się do aplikacji. Pamiętaj o tym.
Jednak na hostingu współdzielonym port 18080 jest dostępny dla każdego innego użytkownika
tego samego serwera - wystarczy że zna numer portu.
Co to oznacza w praktyce:
- Nie wystawiaj przez tę aplikację wrażliwych danych osobowych
- Nie przechowuj haseł ani tokenów dostępowych w odpowiedziach API
- Jeśli aplikacja wymaga autoryzacji - koniecznie ją włącz
- To środowisko testowe i deweloperskie - nie produkcyjne
Jeśli potrzebujesz pełnej izolacji - BiedaHosting nie jest odpowiednim miejscem.
Krok 5 - Reverse Proxy w .htaccess
Dodaj plik .htaccess w folderze public_html
żeby aplikacja była dostępna pod domeną:
RewriteEngine On
RewriteRule ^(.*)$ http://127.0.0.1:18080/$1 [P,L]
Wchodząc na twojadomena.deploy.net.pl ruch jest przekierowywany
do aplikacji Spring Boot na porcie 18080.
Krok 6 - Watchdog
Aplikacje Java na hostingu współdzielonym mogą być ubijane przez system.
Poniższy watchdog monitoruje aplikację i automatycznie ją podnosi gdy padnie -
wybierając wolny port z listy i aktualizując .htaccess.
Zapisz jako $HOME/java/testapp/watchdog.sh:
#!/bin/bash
# --- konfiguracja ---
APP_NAME="test-app"
JAR_PATH="$HOME/java/testapp/test-app-1.0-SNAPSHOT.jar"
JAVA_BIN="$HOME/java/testapp/custom-runtime/bin/java"
LOG_FILE="$HOME/java/testapp/app.log"
PID_FILE="$HOME/java/testapp/app.pid"
HTACCESS_FILE="$HOME/public_html/.htaccess"
source $HOME/.bash_profile
export TMUX_TMPDIR=$HOME/my_tmux_tmp
# lista portów do wykorzystania
PORTS=(18080 18081 18082 18083 18084)
# komenda uruchamiająca aplikację
JAVA_CMD="$JAVA_BIN -Djava.io.tmpdir=$HOME/tmp -jar $JAR_PATH"
# wzorzec do podmiany w .htaccess
HTACCESS_PATTERN='http://127\.0\.0\.1:[0-9]+'
# --- funkcje ---
is_running() {
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p "$PID" > /dev/null 2>&1; then
return 0
fi
fi
if pgrep -f "$JAR_PATH" > /dev/null 2>&1; then
return 0
fi
return 1
}
find_free_port() {
for PORT in "${PORTS[@]}"; do
HEX_PORT=$(printf '%04X' "$PORT")
if ! grep -qi ":$HEX_PORT" /proc/net/tcp; then
echo "$PORT"
return 0
fi
done
return 1
}
update_htaccess() {
local NEW_PORT="$1"
if [ ! -f "$HTACCESS_FILE" ]; then
log "Brak pliku .htaccess: $HTACCESS_FILE"
return 1
fi
cp "$HTACCESS_FILE" "$HTACCESS_FILE.bak"
sed -i -E "s|$HTACCESS_PATTERN|http://127.0.0.1:$NEW_PORT|g" "$HTACCESS_FILE"
log "Zaktualizowano .htaccess -> port $NEW_PORT"
}
start_app() {
local PORT="$1"
local SESSION_NAME="${APP_NAME}-${PORT}"
log "Uruchamiam aplikację na porcie $PORT w tmux"
tmux kill-session -t "$SESSION_NAME" >/dev/null 2>&1
tmux new-session -d -s "$SESSION_NAME" \
"$JAVA_CMD --server.port=$PORT --server.tomcat.basedir=$HOME/tomcat --server.address=127.0.0.1 >> '$LOG_FILE' 2>&1"
sleep 5
PID=$(pgrep -f "$JAR_PATH.*$PORT" | head -n1)
if [ -n "$PID" ] && ps -p "$PID" >/dev/null 2>&1; then
echo "$PID" > "$PID_FILE"
log "Aplikacja uruchomiona, PID=$PID, sesja=$SESSION_NAME"
update_htaccess "$PORT"
else
log "Nie udało się uruchomić aplikacji"
return 1
fi
}
timestamp() {
date '+%Y-%m-%d %H:%M:%S'
}
log() {
echo "[$(timestamp)] $1"
}
# --- główna logika ---
if is_running; then
log "Aplikacja działa"
exit 0
fi
log "Aplikacja nie działa, szukam wolnego portu..."
FREE_PORT=$(find_free_port)
if [ -z "$FREE_PORT" ]; then
log "Brak wolnych portów z listy: ${PORTS[*]}"
exit 1
fi
start_app "$FREE_PORT"
Nadaj uprawnienia i dodaj do crona:
chmod +x $HOME/java/testapp/watchdog.sh
w panelu directadmin przejdz do ustawień crona i ustaw sprawdzania np. co pół godziny
*/30 * * * * /home/twojlogin/java/testapp/watchdog.sh >> /home/twojlogin/java/testapp/watchdog.log 2>&1
Jak działa watchdog?
- Co 30 minut cron uruchamia skrypt
- Sprawdza czy aplikacja działa przez PID file i pgrep
- Jeśli działa - kończy, wszystko OK
- Jeśli nie działa - szuka wolnego portu przez
/proc/net/tcp - Uruchamia aplikację w nowej sesji tmux na wolnym porcie
- Automatycznie aktualizuje
.htaccessz nowym portem - Loguje wszystko do
watchdog.log
Podsumowanie
Aplikacja Spring Boot działa na hostingu współdzielonym. Kluczem jest jlink- bez tego nie zmieścilibyśmy się na bieda25.
Rozmiar na dysku:
- custom-runtime (jlink): ~60 MB
- fat JAR Spring Boot: ~40 MB
- Razem: ~100 MB - mieści się na bieda25 z zapasem
Co działa:
- ✔ Aplikacja Spring Boot dostępna przez domenę
- ✔ Minimalne JRE przez jlink około 60 MB
- ✔ Automatyczny restart po ubiciu przez system
- ✔ Dynamiczna zmiana portu i aktualizacja .htaccess
- ✔ Logowanie zdarzeń
Ograniczenia:
- ⚠ Hosting testowy - nie do produkcji
- ⚠ Aplikacja może być ubijana przez system
- ⚠ Port dostępny dla innych użytkowników serwera
- ⚠ Moduły jlink zależą od Twojej aplikacji - sprawdź jdeps
Chcesz przetestować? Załóż konto na BiedaHosting.pl - 14 dni za darmo, bez karty kredytowej.