Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6893818
LPD-62912 Add configs for SQL Server
anthony-chu Sep 30, 2025
441b2c9
LPD-62912 Include SQL Server JDBC jar in bundle
anthony-chu Sep 30, 2025
3f76e26
LPD-62912 Reuse DB2 database results for SQL Server
anthony-chu Sep 30, 2025
020f54d
LPD-62912 Add recipe files for SQL Server
anthony-chu Sep 30, 2025
730a4f4
LPD-62912 Optionally change ownership for SQL Server files in data-he…
anthony-chu Sep 30, 2025
bd54b02
LPD-62912 Expose property for SQL Server
anthony-chu Sep 30, 2025
9829c00
LPD-62912 Update README
anthony-chu Sep 30, 2025
1fe39ac
LPD-62912 Copy as root
anthony-chu Sep 30, 2025
9473df8
LPD-62912 Using busybox is sufficient
anthony-chu Sep 30, 2025
6b87728
LPD-62912 Convert to elif statements
anthony-chu Oct 1, 2025
1bf9e94
LPD-62912 Add restore to entrypoint
anthony-chu Oct 1, 2025
531744d
LPD-62912 Update condition
anthony-chu Oct 1, 2025
4f8a859
LPD-62912 Add config for database type
anthony-chu Oct 1, 2025
c73b844
LPD-62912 Consolidate jdbc driver tasks into one
anthony-chu Oct 1, 2025
f196aea
LPD-62912 Add missing MariaDB config for consistency
anthony-chu Oct 1, 2025
630271b
LPD-62912 Run copy task conditionally
anthony-chu Oct 1, 2025
f6ce535
LPD-62912 Add mssql jdbc jar to .gitignore
anthony-chu Oct 1, 2025
c1c5f01
LPD-62912 uses the configuration itself to conditionally run the task
drewbrokke Oct 2, 2025
53a0b8f
LPD-62912 Ensure dump is owned by mssql user when using SQL Server
anthony-chu Oct 8, 2025
4b2d942
LPD-62912 Ensure column name is single quoted to avoid keyword
anthony-chu Oct 8, 2025
e631132
LPD-62912 Include backup file for sql server
anthony-chu Oct 8, 2025
44dbd38
LPD-62912 Fix backup file path
anthony-chu Oct 8, 2025
467a68b
LPD-62912 Return empty map if no results are found
anthony-chu Oct 8, 2025
54254f6
LPD-62912 Fix database file location
anthony-chu Oct 8, 2025
d2e5d00
LPD-62912 Fix health check
anthony-chu Oct 8, 2025
70538d9
LPD-62912 Use early returns
anthony-chu Oct 8, 2025
7ae54a9
LPD-62912 Make entrypoint echos clearer
anthony-chu Oct 8, 2025
1736a2d
LPD-62912 Fix DB type
anthony-chu Oct 9, 2025
cdd3244
LPD-62912 Field not used
anthony-chu Oct 9, 2025
121e76c
LPD-62912 Add missing documentation
anthony-chu Oct 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
**/*.iml
**/*.so
**/*db2jcc4.jar
**/*mssql-jdbc-12.10.1.jre11.jar
**/*dxp-license-*.xml
**/*hotfix*.zip
**/.classpath
Expand Down
8 changes: 6 additions & 2 deletions Dockerfile.helper
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ FROM busybox:latest

ARG DATA_DIRECTORY=data

USER 1000
COPY --chown=1000:1000 ${DATA_DIRECTORY} /container-data

COPY --chown=1000:1000 ${DATA_DIRECTORY} /container-data
RUN ([ -d /container-data/sqlserver ] && addgroup --gid 10001 mssql && adduser -S -s /usr/sbin/nologin -h /home/mssql --disabled-password -G mssql -u 10001 mssql) || echo

RUN ([ -d /container-data/sqlserver ] && chown -R 10001:10001 /container-data/sqlserver) || echo

USER 1000
33 changes: 33 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ To shut down the environment, run `./gradlew stop`.

- [Enable MySQL 8.4](#enable-mysql-84)
- [Enable PostgreSQL 16.3](#enable-postgresql-163)
- [Enable DB2 11.5](#enable-db2-115)
- [Enable MariaDB 10.6](#enable-mariadb-106)
- [Enable Microsoft SQL Server 2022](#enable-microsoft-sql-server-2022)
- [Import a database dump](#import-a-database-dump)
- [Enable database partitioning (MySQL and PostgreSQL only)](#enable-database-partitioning-mysql-and-postgresql-only)
- [Configure database port](#configure-database-port)
Expand Down Expand Up @@ -228,6 +231,36 @@ Set the `lr.docker.environment.service.enabled[postgres]` property to `true` or
lr.docker.environment.service.enabled[postgres]=true
```

#### Enable DB2 11.5

Set the `lr.docker.environment.service.enabled[db2]` property to `true` or `1` in `gradle.properties`.

`gradle.properties`:

```properties
lr.docker.environment.service.enabled[db2]=true
```

#### Enable MariaDB 10.6

Set the `lr.docker.environment.service.enabled[mariadb]` property to `true` or `1` in `gradle.properties`.

`gradle.properties`:

```properties
lr.docker.environment.service.enabled[mariadb]=true
```

#### Enable Microsoft SQL Server 2022

Set the `lr.docker.environment.service.enabled[sqlserver]` property to `true` or `1` in `gradle.properties`.

`gradle.properties`:

```properties
lr.docker.environment.service.enabled[sqlserver]=true
```

#### Import a database dump

Database dump files can be added to the `./dumps` directory at the root of the Workspace. They will automatically be copied into the database container.
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ buildDockerImage {
}

dependsOn ":checkForLiferayLicense"
dependsOn ":prepareDB2JDBCDriver"
dependsOn ":prepareJDBCDriver"

mustRunAfter ":importDatabaseDumps"
}

clean {
dependsOn ":cleanPrepareDB2JDBCDriver"
dependsOn ":cleanPrepareJDBCDriver"
dependsOn ":cleanPrepareHotfixes"
dependsOn ":cleanPrepareSelfSignedCert"
dependsOn ":cleanPrepareWebserverConfig"
Expand All @@ -144,7 +144,7 @@ clean {
}

dockerDeploy {
dependsOn ":prepareDB2JDBCDriver"
dependsOn ":prepareJDBCDriver"
dependsOn ":prepareHotfixes"
dependsOn ":prepareYourKitAgent"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,26 +169,33 @@ class Config {
this.useClustering = this.useLiferay && this.clusterNodes > 0

if (this.services.contains("db2")) {
this.databaseType = "db2"
this.useDatabase = true
this.useDatabaseDB2 = true
this.dockerContainerDatabase = "${this.namespace}-database-db2"
}

if (this.services.contains("mariadb")) {
this.databaseType = "mariadb"
this.useDatabase = true
this.useDatabaseMariaDB = true
}

if (this.services.contains("mysql")) {
this.databaseType = "mysql"
this.useDatabase = true
this.useDatabaseMySQL = true
this.dockerContainerDatabase = "${this.namespace}-database-mysql"
}

if (this.services.contains("postgres")) {
this.databaseType = "postgres"
this.useDatabase = true
this.useDatabasePostgreSQL = true
this.dockerContainerDatabase = "${this.namespace}-database-postgres"
}

if (this.services.contains("sqlserver")) {
this.databaseType = "sqlserver"
this.useDatabase = true
this.useDatabaseSQLServer = true
}

if (this.services.contains("webserver_http") && this.services.contains("webserver_https")) {
Expand Down Expand Up @@ -277,10 +284,10 @@ class Config {
public List<Map<String, String>> companyVirtualHosts = null
public List<String> composeFiles = new ArrayList<String>()
public String databaseName = "lportal"
public String databaseType = ""
public boolean databasePartitioningEnabled = false
public String dataDirectory = "data"
public Map<String, String> defaultCompanyVirtualHost = null
public String dockerContainerDatabase = null
public String dockerImageLiferay = null
public boolean dockerImageLiferayDXP = false
public boolean glowrootEnabled = false
Expand All @@ -300,6 +307,7 @@ class Config {
public boolean useDatabaseMariaDB = false
public boolean useDatabaseMySQL = false
public boolean useDatabasePostgreSQL = false
public boolean useDatabaseSQLServer = false
public boolean useLiferay = false
public boolean useWebserverHttp = false
public boolean useWebserverHttps = false
Expand Down
21 changes: 19 additions & 2 deletions buildSrc/src/main/groovy/docker-common.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ ext {

println waitForCommand("docker run --rm -v ${volumeName}:/target busybox:latest du -sh /target/${targetName}")

if (config.useDatabaseSQLServer) {
waitForCommand("docker run --rm -v ${volumeName}:/target busybox:latest chown 10001:10001 /target/${targetName}")
}

println "Copied file ${sourcePath} to ${volumeName}"
}

Expand Down Expand Up @@ -50,9 +54,13 @@ ext {
return toResultRows(results, /,/)
}

if (config.useDatabaseDB2) {
if (config.useDatabaseDB2 || config.useDatabaseSQLServer) {
List<String> results = waitForCommand("${getDatabaseAccessCommand(schema)} \"${sql}\"").split("\n").minus("")

if (results.size() <= 1) {
return Collections.emptyMap()
}

results.removeLast()
results.remove(1)

Expand Down Expand Up @@ -98,7 +106,12 @@ ext {
return config.companyVirtualHosts
}

config.companyVirtualHosts = executeSQLQuery("select companyId, hostname, webId from VirtualHost inner join Company using (companyId) where layoutSetId = 0", config.databaseName)
if (config.useDatabaseSQLServer) {
config.companyVirtualHosts = executeSQLQuery("select VirtualHost.companyId, hostname, webId from VirtualHost inner join Company on (VirtualHost.companyId = Company.companyId) where layoutSetId = 0", config.databaseName)
}
else {
config.companyVirtualHosts = executeSQLQuery("select companyId, hostname, webId from VirtualHost inner join Company using (companyId) where layoutSetId = 0", config.databaseName)
}

return config.companyVirtualHosts
}
Expand Down Expand Up @@ -134,6 +147,10 @@ ext {
"docker compose exec --user db2admin -it database /opt/ibm/db2/V11.5/bin/db2"
].join("\n")
}

if (config.useDatabaseSQLServer) {
return "docker compose exec -it database /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -C -P Liferay123 -d ${config.databaseName} -Q"
}
}

getCompanyDefaultWebId = {
Expand Down
5 changes: 3 additions & 2 deletions buildSrc/src/main/groovy/docker-database-saas.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ ext {
disableUserObjectValidations = {
String schema ->

executeSQLQuery("update ObjectValidationRule set active_ = false where objectDefinitionId in (select objectDefinitionId from ObjectDefinition where externalReferenceCode = 'L_USER')", schema)
executeSQLQuery("update ObjectValidationRule set active_ = 'false' where objectDefinitionId in (select objectDefinitionId from ObjectDefinition where externalReferenceCode = 'L_USER')", schema)

println "Disabled object validation users for User system object in schema ${schema}"
}
Expand Down Expand Up @@ -253,7 +253,7 @@ ext {

sanitizePortalPreferenceValues(schema, sanitizedPreferences)

executeSQLQuery("update MBMailingList set inServerName = 'fake-pop3-host', outServerName = 'fake-smtp-host', inPassword = 'fake-pop3-password', outPassword = 'fake-smtp-password', active_ = false", schema)
executeSQLQuery("update MBMailingList set inServerName = 'fake-pop3-host', outServerName = 'fake-smtp-host', inPassword = 'fake-pop3-password', outPassword = 'fake-smtp-password', active_ = 'false'", schema)

println "Sanitized known POP and SMTP configurations in schema ${schema}"
}
Expand Down Expand Up @@ -457,6 +457,7 @@ tasks.register("copyDatabaseDumpsToDumpsVolume") {
waitForCommand("docker compose create database")

fileTree("dumps") {
include "**/*.bak"
include "**/*.sql"
include "**/*.sql.gz"
include "**/*.gz"
Expand Down
14 changes: 10 additions & 4 deletions buildSrc/src/main/groovy/docker-liferay-bundle.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ project.plugins.apply "docker-common"

configurations {
db2
sqlserver
}

dependencies {
db2 group: "com.ibm.db2.jcc", name: "db2jcc", version: "db2jcc4"
sqlserver group: "com.microsoft.sqlserver", name: "mssql-jdbc", version: "12.10.1.jre11"
}

Closure<Boolean> isValidLicenseFile = {
Expand Down Expand Up @@ -190,15 +192,19 @@ tasks.register("checkForLiferayLicense") {
}
}

tasks.register("prepareDB2JDBCDriver", Copy) {
Configuration dbDriverConfiguration = configurations.findByName(config.databaseType)

tasks.register("prepareJDBCDriver", Copy) {
onlyIf("using the Liferay service") {
config.useLiferay
}
onlyIf("using the DB2 database") {
config.useDatabaseDB2
onlyIf("there is a database driver to install") {
dbDriverConfiguration != null
}

from configurations.db2
from {
dbDriverConfiguration
}
into "configs/common/tomcat/webapps/ROOT/WEB-INF/shielded-container-lib"
}

Expand Down
20 changes: 20 additions & 0 deletions compose-recipes/sqlserver/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM mcr.microsoft.com/mssql/server:2022-CU21-ubuntu-22.04

USER root

RUN mkdir -p /var/opt/mssql/backups /var/opt/mssql/data
RUN chown -R mssql:mssql /var/opt/mssql/
RUN touch /startup_log.txt
RUN chown mssql:mssql /startup_log.txt

COPY entrypoint.sh /init/
COPY init.sql /init/
COPY reinit.sql /init
COPY restore.sql /init

RUN chown -R mssql:mssql /init && \
chmod a+x /init/entrypoint.sh

USER mssql

ENTRYPOINT ["/bin/bash", "/init/entrypoint.sh"]
7 changes: 7 additions & 0 deletions compose-recipes/sqlserver/clustering.sqlserver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
liferay-cluster-node:
environment:
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_DRIVER_UPPERCASEC_LASS_UPPERCASEN_AME=com.microsoft.sqlserver.jdbc.SQLServerDriver
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_PASSWORD=Liferay123
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_URL=jdbc:sqlserver://database:1433;databaseName=lportal;Encrypt=True;TrustServerCertificate=True
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_USERNAME=sa
79 changes: 79 additions & 0 deletions compose-recipes/sqlserver/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash

_sqlcmd="/opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P ${MSSQL_SA_PASSWORD}"

_has_backup_file() {
if [[ $(find /var/opt/mssql/backups -type f -iname "*.bak") ]]; then
echo true
fi
}

_has_database_files() {
local database_name=${1}

if [[ $(find /var/opt/mssql/data -type f -iname "${database_name}.*") ]]; then
echo true
fi
}

_is_database_present() {
local database_name=${1}

if [[ $(${_sqlcmd} -Q "select name from sys.databases" | grep "${database_name}") ]]; then

echo true
fi
}

create_database() {
local database_name=${1}

if [[ $(_is_database_present ${database_name}) ]]; then
echo "[entrypoint] Database ${database_name} is present; skipping database creation"

return
fi

if [[ $(_has_backup_file) ]]; then
echo "[entrypoint] Database backup found; restoring database ${database_name}..."

sed -i "s,%DATABASE_NAME%,${database_name},g" /init/restore.sql

local backup_file=$(find /var/opt/mssql/backups -type f -iname "*.bak")

sed -i "s,%BACKUP_FILE%,${backup_file},g" /init/restore.sql

${_sqlcmd} -i /init/restore.sql

return
fi

if [[ $(_has_database_files ${database_name}) ]]; then
echo "Database files found; reattaching database ${database_name}..."

sed -i "s,%DATABASE_NAME%,${database_name},g" /init/reinit.sql

${_sqlcmd} -i /init/reinit.sql

return
fi

echo "[entrypoint] Could not find database ${database_name}; creating database..."

sed -i "s,%DATABASE_NAME%,${database_name},g" /init/init.sql

${_sqlcmd} -i /init/init.sql
}

main() {
until ${_sqlcmd} -Q "SELECT 1"; do
sleep 1
echo "[entrypoint] Waiting for SQL Server to be available..."
done

create_database ${COMPOSER_DATABASE_NAME}
}

main & /opt/mssql/bin/sqlservr

wait
2 changes: 2 additions & 0 deletions compose-recipes/sqlserver/init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE DATABASE %DATABASE_NAME%
GO
10 changes: 10 additions & 0 deletions compose-recipes/sqlserver/liferay.sqlserver.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
liferay:
depends_on:
database:
condition: service_healthy
environment:
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_DRIVER_UPPERCASEC_LASS_UPPERCASEN_AME=com.microsoft.sqlserver.jdbc.SQLServerDriver
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_PASSWORD=Liferay123
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_URL=jdbc:sqlserver://database:1433;databaseName=lportal;Encrypt=True;TrustServerCertificate=True
- LIFERAY_JDBC_PERIOD_DEFAULT_PERIOD_USERNAME=sa
Loading