Getting started with GitLab-CI: Deploy your app
In the third post of our series about the GitLabCI, we walk you through the process of creating a spring boot app and deploying it on a linux server. In our case the deployment is just moving a spring boot jar around. Obviously you can use this approach to deploy container images or other file based deployments as well.
We assume that you are familiar with simple GitLab-CI configurations, otherwise we suggest to first read our getting started guide and then come back.
What you will achieve
Each build can be deployed with one click and tagged versions are directly deployed.
What you will need
- An account on a GitLab-Server (for example gitlab.com)
- A target linux server with ssh-server
- SSH key pair without password
- A sample program with initial configuration
- Basic knowledge about the GitLab
- Git in Version 2.0.0 or later
- Jdk 1.8
- Maven 3.0+
Set up project
You can use any maven project in combination with the following GitLab-CI configuration or a similar one. If you have none on hand you can create one with spring initializer or use our sample programm from the getting started guide.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
image: maven:3.5.0-jdk-8 buildAndTest: script: - mvn verify --batch-mode artifacts: paths: - target/* expire_in: 5min result: script: - mv target/*.jar . artifacts: paths: - *.jar expire_in: 1d only: - tags |
Until now, we automatically build our project, run unit and integration tests. In addition we provide all tagged versions as artifacts (for one day). So we can download this jar-file and deploy it manually.
Set up linux server
Before we can add a deploy job on the GitLab-server we have to set up the application server. The application server has to be enabled to start and stop the app remotely. In addition the app should start on server start up.
Notice that the location of system configuration is distribution dependent. For example you find the configuration with debian, ubuntu in /etc/systemd/system and for ArchLinux or CentOS in /usr/lib/systemd/system.
So we create a system daemon by implementing the following file in -systemdConfig-/web-demo.service
as root.
1 2 3 4 5 6 7 8 9 10 11 |
[Unit] Description=web demo service After=network.target [Service] ExecStart=/usr/bin/java -jar /opt/web-demo.jar User=user Group=users [Install] WantedBy=multi-user.target |
The service has to be registered using the following command: ‘sudo systemctl enable web-demo.service’. In order to run the service without any user interaction the password is disabled by using visudo and adding the following lines:
1 2 |
%users ALL = NOPASSWD: /usr/sbin/service web-demo start %users ALL = NOPASSWD: /usr/sbin/service web-demo stop |
Set up secret variables
If you have a public repository or you just do not want to save passwords in Git, another way to insert them in is needed. GitLab-CI allows to set secret variables in the settings/CI settings.
In this case a SSH key pair for login and the public SSH key of the target server is needed.
For readers who are not familiar with the concept of SSH keys, we recommend first to read the GitLab documentation for SSH and then come back.
Firstly the private key is saved in the variable SSH_PRIVATE_KEY. But it is important that the SSH key is not protected with a passphrase, otherwise the script will prompt for it. Secondly the public SSH key of the server is stored in the variable ‘KNOWN_HOST’. You can gather it with ssh-keyscan.
Deployment
After setting up the target server, .gitlab-ci.yml can be extended. In the part after before_script the runner is enabled to connect to the server. For this a private key and the public host key is added to avoid man in the middle attacks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
image: maven:3.5.0-jdk-8 before_script: - which ssh-agent - eval $(ssh-agent -s) - ssh-add <(echo "$SSH_PRIVATE_KEY") - '[[ -f /.dockerenv ]] && mkdir -p ~/.ssh && echo "$KNOWN_HOST" > ~/.ssh/known_hosts' buildAndTest: script: - mvn verify artifacts: paths: - target/* expire_in: 5min autoDeploy: stage: deploy script: - mvn package - mv target/*.jar web-demo.jar - ssh user@server 'sudo service web-demo stop' - scp web-demo.jar user@server:/opt/ - ssh user@project 'sudo service web-demo start' artifacts: paths: - *.jar expire_in: 10d only: - tags |
The deployment can now be achieved by connecting to the server, stop the service, copy the new jar and start the service again. The only parameter ensures that the deployment job is restricted on tagged commits. To supplement the configuration with the manual deployment, the same script part is used and adjusted to the runner conditions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[...] manualDeploy: stage: deploy script: - mvn package - mv target/*.jar web-demo.jar - ssh user@server 'sudo service web-demo stop' - scp web-demo.jar user@server:/opt/ - ssh user@server 'sudo service web-demo start' artifacts: paths: - *.jar expire_in: 1d when: manual |
Conclusion
We have seen how to set up the server and how we can configurate the GitLab-CI to manage deployment to a linux server.