Sebelumnya kita udah membuat deploy untuk system traditional deployment yaitu menggunakan war
bundle, sekarang saya akan buat yang sistem deployment as service di Linux.
Berapa yang harus kita siapkan diantaranya:
- Project spring-boot yang embeded Unix service
- Systemd script
- Gitlab repository
- Gitlab CI/CD
- User to start/stop/restart service
Create project Springboot
Ok sekarang kita buat project springbootnya dari springboot starter dengan properties seperti berikut:
- GroupId:
com.maryanto.dimas.example
- ArtifactId:
springboot-systemd
- Dependencies:
- Web
- Lombok
- DevTools
- Actuator
Kemudian click Generate Project, setelah itu kita rubah configurasi pom.xml
menjadi seperti berikut:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!-- dependencies -->
</dependencies>
<build>
<!-- jar file name is springboot-systemctl.jar -->
<finalName>springboot-systemctl</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>
Setelah itu kita harus kasih spesifikasi port yang akan digunakan dengan mengedit file application.properties
di dalam folder src/main/resources
seperti berikut:
server.port=1234
spring.application.name=springboot-systemctl
Sekarang kita siapkan dulu file .jar
dengan menggunakan perintah seperti berikut:
mvn clean package
Maka file springboot-systemctl.jar
akan terbuat di dalam folder target/
seperti berikut hasil compilenya:
target
├── springboot-systemctl.jar
Ada 2 .jar
file kita pilih aja yang springboot-systemctl.jar
kemudian kita coba jalankan dengan perintah seperti berikut:
java -jar target/springboot-systemctl.jar
# logs
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.6.RELEASE)
2018-10-26 11:19:50.676 INFO 3013 --- [ main] c.m.dimas.example.GitlabCIExample : Starting GitlabCIExample v0.0.1-SNAPSHOT on Dimass-MacBook-Pro.local with PID 3013 (/Users/dimasm93/Workspaces/examples/gitlab-ci-springboot-systemd/target/gitlab-ci.jar started by dimasm93 in /Users/dimasm93/Workspaces/examples/gitlab-ci-springboot-systemd)
2018-10-26 11:19:50.683 INFO 3013 --- [ main] c.m.dimas.example.GitlabCIExample : No active profile set, falling back to default profiles: default
2018-10-26 11:19:50.760 INFO 3013 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@2db0f6b2: startup date [Fri Oct 26 11:19:50 WIB 2018]; root of context hierarchy
2018-10-26 11:19:52.767 INFO 3013 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 1234 (http)
2018-10-26 11:19:52.831 INFO 3013 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2018-10-26 11:19:52.831 INFO 3013 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.34
2018-10-26 11:19:54.052 INFO 3013 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-10-26 11:19:54.082 INFO 3013 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-10-26 11:19:54.082 INFO 3013 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-10-26 11:19:54.361 INFO 3013 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2018-10-26 11:19:54.371 INFO 3013 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-10-26 11:19:54.372 INFO 3013 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2018-10-26 11:19:54.373 INFO 3013 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto protected java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springframework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-10-26 11:19:54.431 INFO 3013 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-10-26 11:19:54.504 INFO 3013 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 1234 (http) with context path ''
2018-10-26 11:19:54.508 INFO 3013 --- [ main] c.m.dimas.example.GitlabCIExample : Started GitlabCIExample in 4.511 seconds (JVM running for 5.362)
Unix users, to run systemd
Setelum kita membuat script unix systemd, kita buat user unix dulu supaya build dijalankan tanpa menggunakan password super user. Misalnya saya membuat username dengan nama app
seperti berikut:
# interactive mode
sudo -i
# create user with username app
adduser app
# log output
Adding user 'app' ...
Adding new group 'app' (1001) ...
Adding new user 'app' (1001) with group `app' ...
Creating home directory '/home/app' ...
Copying files from '/etc/skel' ...
## enter password
New password:
## enter password again
Retype new password:
passwd: password updated successfully
Kemudian kita copy manual dulu, filer springboot-systemctl.jar
ke servernya dengan perintah seperti berikut:
# create folder applications
ssh app@192.168.1.23 "mkdir -p applications"
# copy jar file to folder application
scp target/springboot-systemctl.jar app@192.168.1.23:~/applications/springboot-systemctl.jar
## log output
# scp target/gitlab-ci.jar.original app@192.168.1.23:~/applications/springboot-systemctl.jar
# app@192.168.1.23's password:
# springboot-systemctl.jar 100% 3492 1.6MB/s 00:00
Setelah file springboot-systemctl.jar
siap, kita siapkan dulu script unix systemd yang disimpan di folder /etc/systemd/system/
dengan nama springboot-systemctl.service
seperti berikut:
[Unit]
Description=springboot-systemctl
After=syslog.target
[Service]
User=app
ExecStart=/home/app/applications/springboot-systemctl.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
Sekarang kita test dulu, dengan merestart service daemon berikut perintahnya:
## reload daemon for systemctl
systemctl daemon-reload
## start service
systemctl start springboot-systemctl.service
## status service
systemctl status springboot-systemctl.service
Setelah servicenya bisa di running, dan statusnya Active kita bisa check dengan menggunakan perintah berikut:
curl http:192.168.1.23:1234/actuator
Create gitlab repository
Setelah itu kita ketahap selanjutnya yaitu membuat repository gitlab, proses ini intinya sama seperti sebelumnya jadi saya kasih stepnya ja ya:
- Create repository, dengan name
gitlab-ci-springboot-systemd
- Setelah itu commit dan push ke repository tersebut
Run systemctl from unix user app
Tahap selajutnya yaitu, kita harus setting supaya user di Unix bisa menjalankan perintah systemd tanpa menggunakan promnt password. sebenarnya bisa menggunakan user lain yaitu ‘root’ tpi terkadang root tidak bisa di buka lewat ssh remote jadi kita pakai user app
saja ya yang kita grant seperti root dengan mengedit file dengan perintah sebagai berikut:
# view user sudo
cat /etc/sudoers
# to grant user app group with root
visudo
Edit menjadi seperti berikut:
# other configuration
# User privilege specification
root ALL=(ALL:ALL) ALL
app ALL=(ALL:ALL) ALL # add this line
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
%app ALL=NOPASSWD: ALL # add this line
# See sudoers(5) for more information on "#include" directives:
Setelai itu coba login sebagai user app
kemudian test perintah berikut:
sudo systemctl restart springboot-systemctl.service
Kalau sudah tidak ada promnt password yang muncul, dan langsung by pass berati configurasi sudah bener
Script gitlab-ci
Tambahakan file .gitlab-ci.yml
di root project seperti berikut:
variables:
MAVEN_CLI_OPTS: "--show-version"
APP_DIR: "/home/app/applications/[groupId]/[artifactId]"
APP_NAME: "[aftifactId]"
cache:
paths:
- .m2/repository
building:
stage: build
script:
- 'mvn $MAVEN_CLI_OPTS clean package install'
only:
- /-release$/
artifacts:
paths:
- target/*.jar
copy-artifact:
stage: deploy
script:
- 'cp -u target/*.jar $APP_DIR/$APP_NAME-$CI_COMMIT_TAG.jar'
- 'rm -rf $APP_DIR/application.jar && ln -s $APP_DIR/$APP_NAME-$CI_COMMIT_TAG.jar $APP_DIR/application.jar'
- 'sudo systemctl restart $APP_NAME.service'
only:
- /-release$/
Kemudian, setelah itu kita buat tags dulu untuk meng-execute script dengan sufix -release
contohnya 1.0.0-release
, 1.0.1-release
dan seterunya.
Setelah itu daftarkan di gitlab runner gitlab-runner
setelah tahapnya sama seperti sebelumnya tinggal kita checkout aja task, jobs dan pipelinenya. Jika sukses hasilnya seperti berikut: