Tuesday, 30 April 2019

Configure Sonarqube external database

Sonarqube documentation says the in-memory database should be used for evaluation purpose. For production purpose, a more scalable solution is needed -- a standalone database.

Despite the warning on the documentation against MySQL, I decided to give it a go anyway because

1. I have already installed a MySQL server locally, and
2. I was just trying to test a solution to a problem

After having created the database scheme, the user, and granted the privileges, I removed the old sonarqube container and attempted to start the new one with the following command.

docker run --name sonarqube\
    -p 9000:9000 \
    -e sonar.jdbc.username=sonarqube \
    -e sonar.jdbc.password=<password> \
    -e sonar.jdbc.url="jdbc:mysql://localhost:3306/sonarqube?useUnicode=true&characterEncoding=utf8" \
    sonarqube

The I got this error.

019.05.01 06:15:52 INFO  web[][o.sonar.db.Database] Create JDBC data source for jdbc:mysql://localhost:3306/sonarqube?useUnicode=true&characterEncoding=utf8
2019.05.01 06:15:53 ERROR web[][o.s.s.p.Platform] Web server startup failed
java.lang.IllegalStateException: Can not connect to database. Please check connectivity and settings (see the properties prefixed by 'sonar.jdbc.').
 at org.sonar.db.DefaultDatabase.checkConnection(DefaultDatabase.java:119)
 at org.sonar.db.DefaultDatabase.start(DefaultDatabase.java:85)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.picocontainer.lifecycle.ReflectionLifecycleStrategy.invokeMethod(ReflectionLifecycleStrategy.java:110)
 at org.picocontainer.lifecycle.ReflectionLifecycleStrategy.start(ReflectionLifecycleStrategy.java:89)
 at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.start(AbstractInjectionFactory.java:84)
 at org.picocontainer.behaviors.AbstractBehavior.start(AbstractBehavior.java:169)
 at org.picocontainer.behaviors.Stored$RealComponentLifecycle.start(Stored.java:132)
 at org.picocontainer.behaviors.Stored.start(Stored.java:110)
 at org.picocontainer.DefaultPicoContainer.potentiallyStartAdapter(DefaultPicoContainer.java:1016)
 at org.picocontainer.DefaultPicoContainer.startAdapters(DefaultPicoContainer.java:1009)
 at org.picocontainer.DefaultPicoContainer.start(DefaultPicoContainer.java:767)
 at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:135)
 at org.sonar.server.platform.platformlevel.PlatformLevel.start(PlatformLevel.java:90)
 at org.sonar.server.platform.platformlevel.PlatformLevel1.start(PlatformLevel1.java:154)
 at org.sonar.server.platform.Platform.start(Platform.java:211)
 at org.sonar.server.platform.Platform.startLevel1Container(Platform.java:170)
 at org.sonar.server.platform.Platform.init(Platform.java:86)
 at org.sonar.server.platform.web.PlatformServletContextListener.contextInitialized(PlatformServletContextListener.java:45)
 at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4817)
 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5283)
 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
 at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1423)
 at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1413)
 at java.util.concurrent.FutureTask.run(FutureTask.java:266)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLException: Cannot create PoolableConnectionFactory (Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.)
 at org.apache.commons.dbcp2.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:2385)
 at org.apache.commons.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:2110)
 at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1563)
 at org.sonar.db.profiling.NullConnectionInterceptor.getConnection(NullConnectionInterceptor.java:31)
 at org.sonar.db.profiling.ProfiledDataSource.getConnection(ProfiledDataSource.java:317)
 at org.sonar.db.DefaultDatabase.checkConnection(DefaultDatabase.java:116)
 ... 30 common frames omitted
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

Guess what, since we have installed sonarqube using docker, and the sonarqube server actually sits inside a container. The localhost IP address is not exposed to the container. The fix is to replace localhost with host.docker.internal:


docker run --name sonarqube\
    -p 9000:9000 \
    -e sonar.jdbc.username=sonarqube \
    -e sonar.jdbc.password=password \
    -e sonar.jdbc.url="jdbc:mysql://host.docker.internal:3306/sonarqube?useUnicode=true&characterEncoding=utf8" \
    sonarqube

No comments:

Post a Comment