Gitlab Continuous Integration npm Background Process
Here is an example of running a process in the background using the systemd service manager.
In this example, Gitlab CI/CD will deploy a React web app in an HTTP server running on Ubuntu.
Step 1: On the runner, create a service unit file
vi /etc/systemd/system/hello-react.service
[Unit]
Description=Hello React service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=gitlab-runner
ExecStart=npx http-server -p 3000 /home/gitlab-runner/hello-react/
[Install]
WantedBy=multi-user.target
Step 2: On the runner, grant the sudo
permission to user gitlab-runner
with no password restriction.
$ sudo usermod -a -G sudo gitlab-runner
$ sudo visudo
Now add the following line to the bottom of the file
gitlab-runner ALL=(ALL) NOPASSWD: ALL
Step 3: In your code repo, create deploy.sh
#!/bin/bash
echo "Build the app for production"
npm run build
echo "Copy over the build"
rm -fr /home/gitlab-runner/hello-react/*
cp -r build/* /home/gitlab-runner/hello-react/
echo "Running server in the background"
sudo systemctl restart hello-react
echo "HTTP server started."
Step 4: In your code repo, update .gitlab-ci.yml
image: node:latest
stages:
- build
- test
- deploy
cache:
paths:
- node_modules/
install_dependecies:
stage: build
script:
- npm install
artifacts:
paths:
- node_modules/
run_unit_tests:
stage: test
script:
- npm test
deploy_app:
stage: deploy
script:
- bash -c './deploy.sh'
That's it. The CI/CD job will finish without halting. The app will be deployed, and you can visit it at http://your-server-ip:3000
According to Tomasz Maczukin on a related GitLab issue:
I think the best solution would be to use some service manager (systemd, runit, upstart, sysv - whatever is present on this system).
On the server you should prepare configuration file to start the service. Then in CI job you would do e.g.
systemctl start tomcat
. This command is expected to exit just after calling and it's service manager (outside of Runner's scope) who starts the process.Process started with Runner, even if you add
nohup
and&
at the end, is marked with process group ID. When job is finished Runner is sending kill signal to whole process group. So any process started directly from CI job will be terminated at job end. Using service manager you're not starting the process in context of Runner's job. Your only notifying a manager to start a process using prepared configuration :)