Skip to content

Commit

Permalink
test(tools/docker): add new Corda v4.12-SNAPSHOT all-in-one image
Browse files Browse the repository at this point in the history
Published on GHCR as
`ghcr.io/hyperledger/cactus-corda-4-12-all-in-one-negotiation:2024-02-13-dev`

1. It is a more bare bones flavor of the previous versions in the sense that it does not support
running the REST API web servers that come with the samples repository at all. It only supports
running the nodes A, B and Notary.
2. There is no Party C because we had to switch over to the negotiation-cordapp example.
3. This flavor of the image supports customizing the log levels of the Corda node through
the file at: tools/docker/corda-all-in-one/corda-v4_12/negotiation-cordapp/log4j2.xml
Note however that applying these changes requires a rebuild of the image so it's still less
convenient than idea lto use, but at least now we have an option to do so.
4. Another new feature of this image compared to the earlier Corda AIO images is that it
uses Ubuntu 22.04 LTS as it's base instead of alpine. This increases the image size a little
but it's well worth the trade-off of having a uniform image base (which is the long term plan)
5. There is a builder stage that can be used to clone an arbitrary branch + SHA combination of
the upstream corda git repository and then build the node .jar file from it which then will be
used by the image to run the nodes. The custom-built .jar file is placed under  /opt/bin/corda.jar
so do not mix that one up with the other one that is provided with the corda kotlin-samples repo.
6. The `run-notary-node.sh`, `run-party-a-node.sh` and `run-party-b-node.sh` scripts were altered
to use the custom-built .jar file mentioned above and this is the reason why this commit adds
a (seeming) clone of these scripts.
7. For now I did not add a CI task for building and publishing the image because even though
that would match the older images, I'm trying to save on CI resources and at the moment we
don't necessarily need a fresh build of this image on each new pull request.
8. Last but not least (first actually) this is also a security adjacent upgrade since using
this image is the precursor to a much bigger change that will see the Corda v4 connector's
dependencies upgraded to Spring Boot v3 and Corda v4.12-SNAPSHOT but we can't do that without
having this image published first if we want to have test-automation verifying those changes.

Signed-off-by: Peter Somogyvari <[email protected]>
  • Loading branch information
petermetz committed Feb 14, 2024
1 parent fb50fb2 commit 2cd1fb2
Show file tree
Hide file tree
Showing 9 changed files with 482 additions and 0 deletions.
15 changes: 15 additions & 0 deletions tools/docker/corda-all-in-one/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ DOCKER_BUILDKIT=1 docker build ./tools/docker/corda-all-in-one/corda-v4_8-flowdb
docker run --rm --privileged caio48-flowdb
```

# cactus-corda-4-12-all-in-one

> This docker image is for `testing` and `development` only.
> Do NOT use in production!
## Usage

### Build and Run Image Locally

```sh
DOCKER_BUILDKIT=1 docker build ./tools/docker/corda-all-in-one/corda-v4_12/ -f ./tools/docker/corda-all-in-one/corda-v4_12/Dockerfile -t caio412
docker run --rm --privileged caio412
```


# cactus-corda-5-all-in-one-solar

> This docker image is for `testing` and `development` only.
Expand Down
118 changes: 118 additions & 0 deletions tools/docker/corda-all-in-one/corda-v4_12/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
FROM ubuntu:22.04 as builder

RUN apt update && apt install openjdk-17-jdk git curl augeas-tools -y
WORKDIR /opt/
RUN git clone https://github.com/corda/corda.git
WORKDIR /opt/corda/

# commit c7514e1c603c077b49987fd79bd77060612967ed (HEAD -> release/os/4.12, upstream/release/os/4.12)
# Author: Chris Cochrane <[email protected]>
# Date: Wed Feb 7 14:46:18 2024 +0000
#
# ENT-11443 Function sig changes to support removing enterprise compiler warnings (#7671)
RUN git switch release/os/4.12
RUN git checkout c7514e1c603c077b49987fd79bd77060612967ed
RUN ./gradlew jar -x test

FROM ubuntu:22.04

RUN apt update && apt install openjdk-17-jdk supervisor openssh-server sudo git curl iputils-ping netcat augeas-tools -y

RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 test

RUN echo 'root:root' | chpasswd

RUN mkdir /var/run/sshd

ARG CORDA_TOOLS_SHELL_CLI_VERSION=4.8.11

WORKDIR /

ENV CACTUS_CFG_PATH=/etc/hyperledger/cactus
RUN mkdir -p $CACTUS_CFG_PATH

RUN curl https://download.corda.net/maven/corda-releases/net/corda/corda-tools-shell-cli/${CORDA_TOOLS_SHELL_CLI_VERSION}/corda-tools-shell-cli-${CORDA_TOOLS_SHELL_CLI_VERSION}-all.jar --output /corda-tools-shell-cli-all.jar
# Make the "corda-shell" alias avaialble on the terminal
RUN java -jar /corda-tools-shell-cli-all.jar install-shell-extensions

# The image has a bleeding edge version of corda baked in for testing conveniece
RUN mkdir -p /opt/bin/
COPY --from=builder /opt/corda/node/capsule/build/libs/corda-4.12-SNAPSHOT.jar /opt/bin/corda.jar

RUN git clone https://github.com/corda/samples-kotlin.git
WORKDIR /samples-kotlin

ARG SAMPLES_KOTLIN_SHA=219750f8da2fd491c3b55c8eea821b1f345fef7d
ARG SAMPLES_KOTLIN_BRANCH=arshadm/ent-6914-upgrade-kotlin19-jdk17

RUN git switch ${SAMPLES_KOTLIN_BRANCH}
RUN git checkout ${SAMPLES_KOTLIN_SHA}

ARG SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH="./Advanced/negotiation-cordapp/"
WORKDIR /samples-kotlin/${SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH}

COPY ./negotiation-cordapp/build.gradle /samples-kotlin/Advanced/negotiation-cordapp/build.gradle

RUN ./gradlew build deployNodes

WORKDIR /

# Configure the OpenSSH server we just installed
RUN augtool 'set /files/etc/ssh/sshd_config/AuthorizedKeysFile ".ssh/authorized_keys /etc/authorized_keys/%u"' && \
augtool 'set /files/etc/ssh/sshd_config/PermitRootLogin yes' && \
augtool 'set /files/etc/ssh/sshd_config/PasswordAuthentication yes' && \
augtool 'set /files/etc/ssh/sshd_config/PermitEmptyPasswords yes' && \
augtool 'set /files/etc/ssh/sshd_config/Port 22' && \
augtool 'set /files/etc/ssh/sshd_config/LogLevel DEBUG2' && \
augtool 'set /files/etc/ssh/sshd_config/LoginGraceTime 10'

# Create the server's key - without this sshd will refuse to start
RUN ssh-keygen -A

# Generate an RSA keypair on the fly to avoid having to hardcode one in the image
# which technically does not pose a security threat since this is only a development
# image, but we do it like this anyway.
RUN mkdir ~/.ssh && \
chmod 700 ~/.ssh/ && \
touch ~/.ssh/authorized_keys

RUN ["/bin/bash", "-c", "ssh-keygen -t rsa -N '' -f $CACTUS_CFG_PATH/corda-aio-image"]
RUN mv $CACTUS_CFG_PATH/corda-aio-image $CACTUS_CFG_PATH/corda-aio-image.key
RUN cp $CACTUS_CFG_PATH/corda-aio-image.pub ~/.ssh/authorized_keys

WORKDIR /samples-kotlin/${SAMPLES_KOTLIN_CORDAPP_SUB_DIR_PATH}

# OpenSSH server
EXPOSE 22

# supervisord web ui/dashboard
EXPOSE 9001

# Party Notary, Party A, Party B RPC ports
EXPOSE 10003 10006 10009

# Jolokia for Party A,B,C and Notary
EXPOSE 7005 7006 7007 7008

# JVM remote debug port
EXPOSE 5005 5006 5008

COPY supervisord.conf /etc/supervisord.conf
COPY run-party-b-node.sh run-notary-node.sh healthcheck.sh run-party-a-node.sh /
COPY ./negotiation-cordapp/log4j2.xml /samples-kotlin/Advanced/negotiation-cordapp/config/dev/log4j2.xml

# By default we only run the absolute minimum which is a single partys node.
# For more complex tests everything else can also be enabled via the env vars
# below so that if needed there is 2 parties, a notary and a dedicated web server
# for all 3 of those nodes.
# "Web server" => the same one as in the official corda samples-kotlin repo
ENV PARTY_A_NODE_ENABLED="true"

ENV PARTY_B_NODE_ENABLED="true"

ENV NOTARY_NODE_ENABLED="true"

ENTRYPOINT ["/usr/bin/supervisord"]
CMD ["--configuration", "/etc/supervisord.conf", "--nodaemon"]

HEALTHCHECK --interval=1s --timeout=5s --start-period=5s --retries=120 CMD /healthcheck.sh
26 changes: 26 additions & 0 deletions tools/docker/corda-all-in-one/corda-v4_12/healthcheck.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

set -e

if [ "$PARTY_A_WEB_SRV_ENABLED" = "true" ]
then
curl -vv -i -X OPTIONS http://127.0.0.1:10009/web/iou/
fi

if [ "$PARTY_B_WEB_SRV_ENABLED" = "true" ]
then
curl -vv -i -X OPTIONS http://127.0.0.1:10012/web/iou/
fi


if [ "$PARTY_A_NODE_ENABLED" = "true" ]
then
curl -v 'http://localhost:7005/jolokia/exec/org.apache.activemq.artemis:address=%22rpc.server%22,broker=%22RPC%22,component=addresses,queue=%22rpc.server%22,routing-type=%22multicast%22,subcomponent=queues/countMessages()/'
fi

if [ "$PARTY_B_NODE_ENABLED" = "true" ]
then
curl -v 'http://localhost:7006/jolokia/exec/org.apache.activemq.artemis:address=%22rpc.server%22,broker=%22RPC%22,component=addresses,queue=%22rpc.server%22,routing-type=%22multicast%22,subcomponent=queues/countMessages()/'
fi

curl -v 'http://localhost:7008/jolokia/exec/org.apache.activemq.artemis:address=%22rpc.server%22,broker=%22RPC%22,component=addresses,queue=%22rpc.server%22,routing-type=%22multicast%22,subcomponent=queues/countMessages()/'
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

import static org.gradle.api.JavaVersion.VERSION_17
import static org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_8

buildscript { //properties that you need to build the project

Properties constants = new Properties()
file("$projectDir/../constants.properties").withInputStream { constants.load(it) }

ext {
corda_release_group = constants.getProperty("cordaReleaseGroup")
corda_core_release_group = constants.getProperty("cordaCoreReleaseGroup")
corda_release_version = constants.getProperty("cordaVersion")
corda_shell_version = corda_release_version
corda_core_release_version = constants.getProperty("cordaCoreVersion")
corda_gradle_plugins_version = constants.getProperty("gradlePluginsVersion")
kotlin_version = constants.getProperty("kotlinVersion")
junit_version = constants.getProperty("junitVersion")
quasar_version = constants.getProperty("quasarVersion")
log4j_version = constants.getProperty("log4jVersion")
slf4j_version = constants.getProperty("slf4jVersion")
corda_platform_version = constants.getProperty("platformVersion").toInteger()
rxjava_version = constants.getProperty("rxJavaVersion")
snappy_version = constants.getProperty("snappyVersion")
//springboot
spring_boot_version = '2.0.2.RELEASE'
spring_boot_gradle_plugin_version = '2.0.2.RELEASE'

testJvmArgs = ['--add-opens', 'java.base/java.time=ALL-UNNAMED', '--add-opens', 'java.base/java.io=ALL-UNNAMED',
'--add-opens', 'java.base/java.util=ALL-UNNAMED', '--add-opens', 'java.base/java.net=ALL-UNNAMED',
'--add-opens', 'java.base/java.nio=ALL-UNNAMED', '--add-opens', 'java.base/java.lang.invoke=ALL-UNNAMED',
'--add-opens', 'java.base/java.security.cert=ALL-UNNAMED', '--add-opens', 'java.base/java.security=ALL-UNNAMED',
'--add-opens', 'java.base/javax.net.ssl=ALL-UNNAMED', '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
'--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED', '--add-opens', 'java.sql/java.sql=ALL-UNNAMED',]
testJvmFxArgs = [ '--add-exports', 'java.base/sun.nio.ch=ALL-UNNAMED',
'--add-exports', 'javafx.base/com.sun.javafx=ALL-UNNAMED',
'--add-exports', 'javafx.base/com.sun.javafx.collections=ALL-UNNAMED']
}

repositories {
mavenLocal()
mavenCentral()

maven { url 'https://download.corda.net/maven/corda-releases' }
}

dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "net.corda.plugins:cordapp:$corda_gradle_plugins_version"
classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version"
classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version"
classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_gradle_plugin_version"
}
}

allprojects { //Properties that you need to compile your project (The application)
apply from: "${rootProject.projectDir}/repositories.gradle"
apply plugin: 'org.jetbrains.kotlin.jvm'

repositories {
mavenLocal()
maven { url 'https://download.corda.net/maven/corda-releases' }
mavenCentral()
maven { url 'https://download.corda.net/maven/corda-dependencies' }
maven { url 'https://jitpack.io' }
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
compilerOptions {
languageVersion = KOTLIN_1_8
apiVersion = KOTLIN_1_8
jvmTarget = JVM_17
javaParameters = true // Useful for reflection.
freeCompilerArgs = ['-Xjvm-default=all-compatibility']
allWarningsAsErrors = true
}
}

jar {
// This makes the JAR's SHA-256 hash repeatable.
preserveFileTimestamps = false
reproducibleFileOrder = true
}
}

apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'net.corda.plugins.quasar-utils'

sourceSets {
main {
resources {
srcDir rootProject.file("config/dev")
}
}
}

//Module dependencis
dependencies {
// Corda dependencies.
cordaProvided "$corda_release_group:corda-core:$corda_release_version"
cordaBootstrapper("$corda_release_group:corda-node-api:$corda_release_version") {
exclude group: "ch.qos.logback", module: "logback-classic"
}
corda "$corda_release_group:corda:$corda_release_version"

// CorDapp dependencies.
cordapp("$corda_release_group:corda-finance-contracts:$corda_release_version")
cordapp("$corda_release_group:corda-finance-workflows:$corda_release_version")
cordapp project(":workflows")
cordapp project(":contracts")

cordaProvided "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
cordaProvided "org.apache.logging.log4j:log4j-web:${log4j_version}"
cordaProvided "org.slf4j:jul-to-slf4j:$slf4j_version"
cordaDriver "net.corda:corda-shell:$corda_shell_version"
}

cordapp {
targetPlatformVersion corda_platform_version.toInteger()
minimumPlatformVersion corda_platform_version.toInteger()
}


task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
nodeDefaults {

cordapp project(':contracts')
cordapp project(':workflows')
runSchemaMigration = true
}
node {
name "O=Notary,L=London,C=GB"
notary = [validating : false]
p2pPort 10002
rpcSettings {
address("0.0.0.0:10003")
adminAddress("0.0.0.0:10043")
}
}
node {
name "O=PartyA,L=London,C=GB"
p2pPort 10005
rpcSettings {
address("0.0.0.0:10006")
adminAddress("0.0.0.0:10046")
}
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
}
node {
name "O=PartyB,L=New York,C=US"
p2pPort 10008
rpcSettings {
address("0.0.0.0:10009")
adminAddress("0.0.0.0:10049")
}
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">

<Properties>
<Property name="log-path">logs</Property>
<Property name="log-name">node-${hostName}</Property>
<Property name="archive">${log-path}/archive</Property>
</Properties>

<ThresholdFilter level="trace"/>

<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
%highlight{%level{length=1} %d{HH:mm:ss} %T %c{1}.%M - %msg%n}{INFO=white,WARN=red,FATAL=bright red blink}
</pattern>>
</PatternLayout>
</Console>

<!-- Will generate up to 10 log files for a given day. During every rollover it will delete
those that are older than 60 days, but keep the most recent 10 GB -->
<RollingFile name="RollingFile-Appender"
fileName="${log-path}/${log-name}.log"
filePattern="${archive}/${log-name}.%d{yyyy-MM-dd}-%i.log.gz">

<PatternLayout pattern="[%-5level] %d{ISO8601}{GMT+0} [%t] %c{1} - %msg%n"/>

<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>

<DefaultRolloverStrategy min="1" max="10">
<Delete basePath="${archive}" maxDepth="1">
<IfFileName glob="${log-name}*.log.gz"/>
<IfLastModified age="60d">
<IfAny>
<IfAccumulatedFileSize exceeds="10 GB"/>
</IfAny>
</IfLastModified>
</Delete>
</DefaultRolloverStrategy>

</RollingFile>
</Appenders>

<Loggers>
<Root level="WARN">
<AppenderRef ref="Console-Appender"/>
<AppenderRef ref="RollingFile-Appender"/>
</Root>
<Logger name="net.corda" level="INFO" additivity="false">
<AppenderRef ref="Console-Appender"/>
<AppenderRef ref="RollingFile-Appender"/>
</Logger>
<Logger name="log4j.logger.org.apache.activemq" level="WARN" additivity="false">
<AppenderRef ref="Console-Appender"/>
<AppenderRef ref="RollingFile-Appender"/>
</Logger>
</Loggers>

</Configuration>
Loading

0 comments on commit 2cd1fb2

Please sign in to comment.