跪拜 Guibai
← Back to the summary

Stop Using nohup java -jar: Three Production-Grade Ways to Daemonize Spring Boot

In the development environment, we are used to casually typing a line:

nohup java -jar my-app.jar &

This indeed runs. But in a production environment, this approach is like walking a tightrope over a high-voltage line.

Why nohup & Doesn't Work?

nohup plus & only puts the process in the background and ignores the hangup signal; it is fundamentally not a process management solution. Using this set in production, you will frequently step on these landmines:

Behind the eight characters "Deploy SpringBoot project on Linux" is actually a practical chain spanning four dimensions: development, operations, security, and performance. You need to use systemd for service supervision, not rely on nohup & to tough it out.

Three production-grade solutions are introduced below, sorted by recommendation level.


Solution 1: Systemd (Most Recommended)

systemd is the standard service manager for modern Linux distributions (CentOS 7+, Ubuntu 16.04+). Using it to manage Spring Boot applications requires no additional software installation, yet its capabilities are far more powerful than nohup.

Step 1: Create a Dedicated Account (Security First)

Absolutely do not run business code as the root user:

# Create a user without login permissions
sudo useradd -r -s /bin/false app_user
# Ensure this user has read/write permissions for the JAR package
sudo chown app_user:app_user /opt/myapp/app.jar

Step 2: Write the Service File

Create a service configuration file at /etc/systemd/system/myapp.service:

[Unit]
Description=My Spring Boot Application
After=syslog.target network.target

[Service]
# Specify the running user to achieve permission isolation
User=app_user
Group=app_user

# Core startup command (recommend specifying the full Java path and JVM parameters)
ExecStart=/usr/bin/java -Xms512m -Xmx512m -XX:+UseG1GC \
    -jar /opt/myapp/app.jar \
    --spring.profiles.active=prod

# Spring Boot graceful shutdown: 143 represents a normal exit via SIGTERM signal
SuccessExitStatus=143

# Auto-restart on crash
Restart=always
RestartSec=10

# Logs are managed by systemd, view with journalctl
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=myapp

[Install]
WantedBy=multi-user.target

Step 3: Activation and Management

# Reload configuration
sudo systemctl daemon-reload

# Set to auto-start on boot (say goodbye to restart anxiety from now on)
sudo systemctl enable myapp

# Start the service
sudo systemctl start myapp

# Check status
sudo systemctl status myapp

# View logs
sudo journalctl -u myapp -f

What If You Don't Have Root Privileges?

Many internal network environments in banks and state-owned enterprises only have regular accounts without sudo privileges. In this case, you can use systemd's User Mode:

# Create a user-level service file
mkdir -p ~/.config/systemd/user/
# Place the .service file in this directory, with the same content but remove the User/Group fields

# Enable and start
systemctl --user enable myapp
systemctl --user start myapp

# Key: Enable linger so the service continues running after the user logs out
# This requires the administrator to execute once:
sudo loginctl enable-linger <username>

Solution 2: Supervisor

If your system is still using an older version like CentOS 6, or you need a lightweight, cross-language process management tool, Supervisor is a very good choice.

Installation and Configuration

# Ubuntu/Debian
sudo apt install supervisor

# CentOS
sudo yum install supervisor

Create the configuration at /etc/supervisor/conf.d/myapp.conf:

[program:myapp]
command=/usr/bin/java -Xms512m -Xmx512m -jar /opt/myapp/app.jar --spring.profiles.active=prod
directory=/opt/myapp
user=app_user
autostart=true
autorestart=true
startsecs=10
stopasgroup=true
killasgroup=true
stopwaitsecs=30
redirect_stderr=true
stdout_logfile=/var/log/myapp/out.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
environment=JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"

Several key configurations must be noted:

Common Management Commands

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start myapp
sudo supervisorctl status

Note: On CentOS 7+, systemd has become the standard, and Supervisor is gradually being deprecated in some distributions. For new projects, prioritize systemd.


Solution 3: Docker + Kubernetes (The Cloud-Native Era Choice)

If your team has already embarked on the path of containerization, Docker + K8s is a more modern solution.

Dockerfile Example

FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/myapp.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Xms512m", "-Xmx512m", "-jar", "app.jar"]

Spring Boot 3.x provides good support for containerization, making containerized deployment very simple.

Advantages of Kubernetes

K8s itself is a production-grade process supervision system:

Docker solves environment consistency, K8s handles automated operations.


Production Environment Checklist

No matter which solution you choose, you must do the following:

Check Item Description
Dedicated Run User Absolutely do not run applications as root
JVM Parameter Tuning Specify -Xms, -Xmx, GC strategy, don't use defaults
Specify Config File Use --spring.config.location to externalize configuration, don't package it into the JAR
Graceful Shutdown SuccessExitStatus=143 allows Spring Boot to properly execute @PreDestroy
Log Management Configure log rotation (Logback's RollingPolicy) to prevent disk from filling up
Auto-Start on Boot systemctl enable or autostart=true
Firewall Confirm the security group and system firewall have opened the application port
Java Version Match Spring Boot 2.7.x uses JDK 8/17, 3.x mandates JDK 17+

Summary

Solution Applicable Scenario Advantages Disadvantages
Systemd Most Linux production environments Native integration, powerful, no install needed Linux only
Supervisor Older systems, cross-language scenarios Lightweight, flexible config Gradually deprecated on CentOS 7+
Docker + K8s Cloud-native, microservice architecture Consistent environment, automated ops High learning curve, high infrastructure requirements

One-sentence suggestion: If your server is CentOS 7+ or Ubuntu 16.04+, use systemd directly; if the company has already adopted containers, go with Docker + K8s; only consider Supervisor for special circumstances.

Stop letting nohup java -jar, a development-phase toy, run in the production environment. What production needs is not "it can run," but "running rock-solid for 365 days."

Comments

Top 1 from juejin.cn, machine-translated. The original thread is authoritative.

melon348

1