Working Docker container

This commit is contained in:
Andreas Svanberg 2025-03-26 12:49:31 +01:00
parent 6039d6b34b
commit 5cfbaa6535
Signed by: ansv7779
GPG Key ID: 729B051CFFD42F92
6 changed files with 223 additions and 20 deletions

45
Dockerfile Normal file

@ -0,0 +1,45 @@
FROM eclipse-temurin:23 AS build
WORKDIR /build
COPY pom.xml mvnw ./
COPY .mvn .mvn
RUN ./mvnw dependency:copy-dependencies \
--activate-profiles=!persistent \
--define includeScope=compile \
--define outputDirectory=lib
RUN ./mvnw dependency:build-classpath \
--activate-profiles=!persistent \
--define includeScope=compile \
--define mdep.outputFile=classpath \
--define mdep.prefix=lib
COPY src src
RUN ./mvnw compile
# Create as small a runtime as possible but Spring/Tomcat needs a lot of modules
RUN jlink \
--output jre \
--add-modules java.sql,java.desktop,java.management,java.naming,java.security.jgss,java.instrument
FROM debian:stable-slim AS runtime
WORKDIR /app
COPY --from=build /build/jre jre
COPY --from=build /build/lib lib
COPY --from=build /build/classpath classpath
COPY --from=build /build/target/classes classes
# Adds the output of Maven compilation to output
RUN echo ":classes" >> classpath
EXPOSE 8080
CMD [ "./jre/bin/java" \
, "-cp", "@classpath" \
, "se.su.dsv.oauth2.AuthorizationServer" \
, "--spring.profiles.active=dev,embedded" \
]

48
pom.xml

@ -23,10 +23,6 @@
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
@ -52,21 +48,6 @@
<version>${jte.version}</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Development tools -->
<dependency>
<groupId>org.springframework.boot</groupId>
@ -146,7 +127,6 @@
<sourceDirectory>${project.basedir}/src/main/resources/templates</sourceDirectory>
<targetDirectory>${project.build.directory}/jte-classes</targetDirectory>
<contentType>Html</contentType>
<binaryStaticContent>true</binaryStaticContent>
<extensions>
<extension>
<className>gg.jte.models.generator.ModelExtension</className>
@ -172,4 +152,32 @@
</plugins>
</build>
<profiles>
<profile>
<id>persistent</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

@ -0,0 +1,91 @@
package se.su.dsv.oauth2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import se.su.dsv.oauth2.admin.repository.ClientRepository;
import se.su.dsv.oauth2.admin.repository.ClientRow;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@Configuration
@Profile("embedded")
public class EmbeddedConfiguration {
@Bean
public ClientRepository clientRepository() {
ArrayList<ClientRow> clients = new ArrayList<>();
ClientRow clientRow = getClientFromEnvironment();
if (clientRow != null) {
clients.add(clientRow);
}
return new InMemoryClientrepository(clients);
}
private static ClientRow getClientFromEnvironment() {
String clientId = System.getenv("CLIENT_ID");
String clientSecret = System.getenv("CLIENT_SECRET");
String redirectUri = System.getenv("CLIENT_REDIRECT_URI");
String scopeString = System.getenv("CLIENT_SCOPES");
return new ClientRow(clientId, clientId, clientId, "dev@localhost",
redirectUri, scopeString, clientSecret);
}
private static class InMemoryClientrepository implements ClientRepository {
private List<ClientRow> clientRows;
private Map<String, List<String>> clientOwners = new HashMap<>();
public InMemoryClientrepository(final List<ClientRow> clients) {
this.clientRows = new ArrayList<>(clients);
}
@Override
public void addNewClient(final ClientRow clientRow) {
clientRows.add(clientRow);
}
@Override
public List<ClientRow> getClients(final Principal owner) {
return List.copyOf(clientRows);
}
@Override
public void addClientOwner(final String principalName, final String id) {
clientOwners.putIfAbsent(id, new ArrayList<>());
clientOwners.get(id).add(principalName);
}
@Override
public void removeOwner(final String id, final String owner) {
clientOwners.putIfAbsent(id, new ArrayList<>());
clientOwners.get(id).remove(owner);
}
@Override
public List<String> getOwners(final String id) {
return clientOwners.getOrDefault(id, List.of());
}
@Override
public Optional<ClientRow> getClientRowById(final String id) {
return clientRows.stream()
.filter(clientRow -> Objects.equals(clientRow.id(), id))
.findAny();
}
@Override
public Optional<ClientRow> getClientRowByClientId(final String clientId) {
return clientRows.stream()
.filter(clientRow -> Objects.equals(clientRow.clientId(), clientId))
.findAny();
}
}
}

@ -2,9 +2,11 @@ package se.su.dsv.oauth2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.simple.JdbcClient;
@Configuration
@Profile("!embedded")
public class PersistentConfiguration {
@Bean
public JDBCClientRepository jdbcClientRepository(JdbcClient jdbcClient) {

@ -0,0 +1,5 @@
gg:
jte:
templateLocation: src/main/resources/templates
developmentMode: false
usePrecompiledTemplates: true

@ -0,0 +1,52 @@
package se.su.dsv.oauth2;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClient;
import org.springframework.web.util.UriComponentsBuilder;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Paths;
import static org.assertj.core.api.Assertions.assertThat;
@Testcontainers
public class EmbeddedContainerTest {
@Container
static GenericContainer<?> container = new GenericContainer<>(
new ImageFromDockerfile()
.withFileFromPath(".", Paths.get(".")))
.withExposedPorts(8080)
.withEnv("CLIENT_ID", "client-id")
.withEnv("CLIENT_SECRET", "client-secret")
.withEnv("CLIENT_REDIRECT_URI", "http://localhost:8080")
.withEnv("CLIENT_SCOPES", "openid profile email");
@Test
public void working_container() {
String baseUri = UriComponentsBuilder.newInstance()
.scheme("http")
.host(container.getHost())
.port(container.getMappedPort(8080))
.toUriString();
RestClient restClient = RestClient.create(baseUri);
ResponseEntity<String> response = restClient
.get()
.retrieve()
.onStatus(ignored -> false) // treat all responses as successful and let asserts fail
.toEntity(String.class);
assertThat(response.getStatusCode())
.isEqualTo(HttpStatus.OK);
assertThat(response.getBody())
.contains("DSV");
}
}