mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Add Docker image as output of build (#4223)
This commit is contained in:
parent
8827801ae6
commit
bbd5369e04
64
docker/build.gradle
Normal file
64
docker/build.gradle
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
evaluationDependsOn(":node:capsule")
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.bmuschko:gradle-docker-plugin:3.4.4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
import com.bmuschko.gradle.docker.DockerRemoteApiPlugin
|
||||||
|
import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage
|
||||||
|
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
apply plugin: DockerRemoteApiPlugin
|
||||||
|
apply plugin: 'application'
|
||||||
|
// We need to set mainClassName before applying the shadow plugin.
|
||||||
|
mainClassName = 'net.corda.core.ConfigExporterMain'
|
||||||
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
|
||||||
|
|
||||||
|
dependencies{
|
||||||
|
compile project(':node')
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
baseName = 'config-exporter'
|
||||||
|
classifier = null
|
||||||
|
version = null
|
||||||
|
zip64 true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
task buildDockerFolder(dependsOn: [":node:capsule:buildCordaJAR", shadowJar]) {
|
||||||
|
doLast {
|
||||||
|
def cordaJar = project(":node:capsule").buildCordaJAR.archivePath
|
||||||
|
project.copy {
|
||||||
|
into new File(project.buildDir, "docker-temp")
|
||||||
|
from "src/bash/run-corda.sh"
|
||||||
|
from cordaJar
|
||||||
|
from shadowJar.archivePath
|
||||||
|
from "src/config/starting-node.conf"
|
||||||
|
from "src/bash/generate-config.sh"
|
||||||
|
from "src/docker/Dockerfile"
|
||||||
|
rename(cordaJar.name, "corda.jar")
|
||||||
|
rename(shadowJar.archivePath.name, "config-exporter.jar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task buildOfficialDockerImage(type: DockerBuildImage, dependsOn: [buildDockerFolder]) {
|
||||||
|
final String runTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
|
||||||
|
//if we are a snapshot, append a timestamp
|
||||||
|
//if we are a release, append RELEASE
|
||||||
|
final String suffix = project.version.toString().toLowerCase().contains("snapshot") ? runTime : "RELEASE"
|
||||||
|
inputDir = new File(project.buildDir, "docker-temp")
|
||||||
|
tags = ["corda/corda-${project.version.toString().toLowerCase()}:${suffix}", "corda/corda-${project.version.toString().toLowerCase()}:latest"]
|
||||||
|
}
|
19
docker/src/bash/example-generate-testnet.sh
Executable file
19
docker/src/bash/example-generate-testnet.sh
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
docker run -ti \
|
||||||
|
-e MY_PUBLIC_ADDRESS="corda-node.example.com" \
|
||||||
|
-e ONE_TIME_DOWNLOAD_KEY="bbcb189e-9e4f-4b27-96db-134e8f592785" \
|
||||||
|
-e LOCALITY="London" -e COUNTRY="GB" \
|
||||||
|
-v $(pwd)/docker/config:/etc/corda \
|
||||||
|
-v $(pwd)/docker/certificates:/opt/corda/certificates \
|
||||||
|
corda/corda-4.0-snapshot:latest config-generator --testnet
|
||||||
|
|
||||||
|
docker run -ti \
|
||||||
|
--memory=2048m \
|
||||||
|
--cpus=2 \
|
||||||
|
-v $(pwd)/docker/config:/etc/corda \
|
||||||
|
-v $(pwd)/docker/certificates:/opt/corda/certificates \
|
||||||
|
-v $(pwd)/docker/persistence:/opt/corda/persistence \
|
||||||
|
-v $(pwd)/docker/logs:/opt/corda/logs \
|
||||||
|
-v $(pwd)/samples/bank-of-corda-demo/build/nodes/BankOfCorda/cordapps:/opt/corda/cordapps \
|
||||||
|
corda/corda-4.0-snapshot:latest
|
27
docker/src/bash/example-join-generic-cz.sh
Executable file
27
docker/src/bash/example-join-generic-cz.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
##in this example the doorman will be running on the host machine on port 8080
|
||||||
|
##so the container must be launched with "host" networking
|
||||||
|
docker run -ti --net="host" \
|
||||||
|
-e MY_LEGAL_NAME="O=EXAMPLE,L=Berlin,C=DE" \
|
||||||
|
-e MY_PUBLIC_ADDRESS="corda.example-hoster.com" \
|
||||||
|
-e NETWORKMAP_URL="https://map.corda.example.com" \
|
||||||
|
-e DOORMAN_URL="https://doorman.corda.example.com" \
|
||||||
|
-e NETWORK_TRUST_PASSWORD="trustPass" \
|
||||||
|
-e MY_EMAIL_ADDRESS="cordauser@r3.com" \
|
||||||
|
-v $(pwd)/docker/config:/etc/corda \
|
||||||
|
-v $(pwd)/docker/certificates:/opt/corda/certificates \
|
||||||
|
corda/corda-4.0-snapshot:latest config-generator --generic
|
||||||
|
|
||||||
|
##set memory to 2gb max, and 2cores max
|
||||||
|
docker run -ti \
|
||||||
|
--memory=2048m \
|
||||||
|
--cpus=2 \
|
||||||
|
-v $(pwd)/docker/config:/etc/corda \
|
||||||
|
-v $(pwd)/docker/certificates:/opt/corda/certificates \
|
||||||
|
-v $(pwd)/docker/persistence:/opt/corda/persistence \
|
||||||
|
-v $(pwd)/docker/logs:/opt/corda/logs \
|
||||||
|
-v $(pwd)/samples/bank-of-corda-demo/build/nodes/BankOfCorda/cordapps:/opt/corda/cordapps \
|
||||||
|
-p 10200:10200 \
|
||||||
|
-p 10201:10201 \
|
||||||
|
corda/corda-4.0-snapshot:latest
|
124
docker/src/bash/generate-config.sh
Executable file
124
docker/src/bash/generate-config.sh
Executable file
@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf '%s\n' "$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help(){
|
||||||
|
|
||||||
|
echo "usage: generate-config <--testnet>|<--generic>"
|
||||||
|
echo -e "\t --testnet is used to generate config and certificates for joining TestNet"
|
||||||
|
echo -e "\t --generic is used to generate config and certificates for joining an existing Corda Compatibility Zone"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateTestnetConfig() {
|
||||||
|
RPC_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \
|
||||||
|
DB_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \
|
||||||
|
MY_PUBLIC_ADDRESS=${MY_PUBLIC_ADDRESS} \
|
||||||
|
MY_P2P_PORT=${MY_P2P_PORT} \
|
||||||
|
MY_RPC_PORT=${MY_RPC_PORT} \
|
||||||
|
MY_RPC_ADMIN_PORT=${MY_RPC_ADMIN_PORT} \
|
||||||
|
NETWORKMAP_URL='https://map.testnet.corda.network' \
|
||||||
|
DOORMAN_URL='https://doorman.testnet.corda.network' \
|
||||||
|
java -jar config-exporter.jar "TEST-NET-COMBINE" "node.conf" "/opt/corda/starting-node.conf" "${CONFIG_FOLDER}/node.conf"
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateGenericCZConfig(){
|
||||||
|
: ${NETWORKMAP_URL:? '$NETWORKMAP_URL, the Compatibility Zone to join must be set as environment variable'}
|
||||||
|
: ${DOORMAN_URL:? '$DOORMAN_URL, the Doorman to use when joining must be set as environment variable'}
|
||||||
|
: ${MY_LEGAL_NAME:? '$MY_LEGAL_NAME, the X500 name to use when joining must be set as environment variable'}
|
||||||
|
: ${MY_EMAIL_ADDRESS:? '$MY_EMAIL_ADDRESS, the email to use when joining must be set as an environment variable'}
|
||||||
|
: ${NETWORK_TRUST_PASSWORD=:? '$NETWORK_TRUST_PASSWORD, the password to the network store to use when joining must be set as environment variable'}
|
||||||
|
|
||||||
|
if [[ ! -f ${CERTIFICATES_FOLDER}/${TRUST_STORE_NAME} ]]; then
|
||||||
|
die "Network Trust Root file not found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
RPC_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \
|
||||||
|
DB_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \
|
||||||
|
MY_PUBLIC_ADDRESS=${MY_PUBLIC_ADDRESS} \
|
||||||
|
MY_P2P_PORT=${MY_P2P_PORT} \
|
||||||
|
MY_RPC_PORT=${MY_RPC_PORT} \
|
||||||
|
MY_RPC_ADMIN_PORT=${MY_RPC_ADMIN_PORT} \
|
||||||
|
java -jar config-exporter.jar "GENERIC-CZ" "/opt/corda/starting-node.conf" "${CONFIG_FOLDER}/node.conf"
|
||||||
|
|
||||||
|
java -Djava.security.egd=file:/dev/./urandom -Dcapsule.jvm.args="${JVM_ARGS}" -jar /opt/corda/bin/corda.jar \
|
||||||
|
initial-registration \
|
||||||
|
--base-directory=/opt/corda \
|
||||||
|
--config-file=/etc/corda/node.conf \
|
||||||
|
--network-root-truststore-password=${NETWORK_TRUST_PASSWORD} \
|
||||||
|
--network-root-truststore=${CERTIFICATES_FOLDER}/${TRUST_STORE_NAME}
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadTestnetCerts() {
|
||||||
|
if [[ ! -f ${CERTIFICATES_FOLDER}/certs.zip ]]; then
|
||||||
|
: ${ONE_TIME_DOWNLOAD_KEY:? '$ONE_TIME_DOWNLOAD_KEY must be set as environment variable'}
|
||||||
|
: ${LOCALITY:? '$LOCALITY (the locality used when registering for Testnet) must be set as environment variable'}
|
||||||
|
: ${COUNTRY:? '$COUNTRY (the country used when registering for Testnet) must be set as environment variable'}
|
||||||
|
curl -L -d "{\"x500Name\":{\"locality\":\"${LOCALITY}\", \"country\":\"${COUNTRY}\"}, \"configType\": \"INSTALLSCRIPT\", \"include\": { \"systemdServices\": false, \"cordapps\": false, \"cordaJar\": false, \"cordaWebserverJar\": false, \"scripts\": false} }" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-X POST "https://testnet.corda.network/api/user/node/generate/one-time-key/redeem/$ONE_TIME_DOWNLOAD_KEY" \
|
||||||
|
-o "${CERTIFICATES_FOLDER}/certs.zip"
|
||||||
|
fi
|
||||||
|
rm -rf ${CERTIFICATES_FOLDER}/*.jks
|
||||||
|
unzip ${CERTIFICATES_FOLDER}/certs.zip
|
||||||
|
}
|
||||||
|
|
||||||
|
GENERATE_TEST_NET=0
|
||||||
|
GENERATE_GENERIC=0
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
case $1 in
|
||||||
|
-h|-\?|--help)
|
||||||
|
show_help # Display a usage synopsis.
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
-t|--testnet)
|
||||||
|
if [[ ${GENERATE_GENERIC} = 0 ]]; then
|
||||||
|
GENERATE_TEST_NET=1
|
||||||
|
else
|
||||||
|
die 'ERROR: cannot generate config for multiple networks'
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
-g|--generic)
|
||||||
|
if [[ ${GENERATE_TEST_NET} = 0 ]]; then
|
||||||
|
GENERATE_GENERIC=1
|
||||||
|
else
|
||||||
|
die 'ERROR: cannot generate config for multiple networks'
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
--) # End of all options.
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-?*)
|
||||||
|
printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
|
||||||
|
;;
|
||||||
|
*) # Default case: No more options, so break out of the loop.
|
||||||
|
break
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
: ${TRUST_STORE_NAME="network-root-truststore.jks"}
|
||||||
|
: ${JVM_ARGS='-Xmx4g -Xms2g -XX:+UseG1GC'}
|
||||||
|
|
||||||
|
|
||||||
|
if [[ ${GENERATE_TEST_NET} == 1 ]]
|
||||||
|
then
|
||||||
|
: ${MY_PUBLIC_ADDRESS:? 'MY_PUBLIC_ADDRESS must be set as environment variable'}
|
||||||
|
downloadTestnetCerts
|
||||||
|
generateTestnetConfig
|
||||||
|
elif [[ ${GENERATE_GENERIC} == 1 ]]
|
||||||
|
then
|
||||||
|
: ${MY_PUBLIC_ADDRESS:? 'MY_PUBLIC_ADDRESS must be set as environment variable'}
|
||||||
|
generateGenericCZConfig
|
||||||
|
else
|
||||||
|
show_help
|
||||||
|
die "No Valid Configuration requested"
|
||||||
|
fi
|
||||||
|
|
10
docker/src/bash/run-corda.sh
Executable file
10
docker/src/bash/run-corda.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
: ${JVM_ARGS='-XX:+UseG1GC'}
|
||||||
|
|
||||||
|
JVM_ARGS="-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap "${JVM_ARGS}
|
||||||
|
|
||||||
|
if [[ ${JVM_ARGS} == *"Xmx"* ]]; then
|
||||||
|
echo "WARNING: the use of the -Xmx flag is not recommended within docker containers. Use the --memory option passed to the container to limit heap size"
|
||||||
|
fi
|
||||||
|
|
||||||
|
java -Djava.security.egd=file:/dev/./urandom -Dcapsule.jvm.args="${JVM_ARGS}" -jar /opt/corda/bin/corda.jar --base-directory=/opt/corda --config-file=/etc/corda/node.conf
|
39
docker/src/config/starting-node.conf
Normal file
39
docker/src/config/starting-node.conf
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
myLegalName=${MY_LEGAL_NAME}
|
||||||
|
p2pAddress=${MY_PUBLIC_ADDRESS}":"${MY_P2P_PORT}
|
||||||
|
rpcSettings {
|
||||||
|
address="0.0.0.0:"${MY_RPC_PORT}
|
||||||
|
adminAddress="0.0.0.0:"${MY_RPC_ADMIN_PORT}
|
||||||
|
}
|
||||||
|
|
||||||
|
security {
|
||||||
|
authService {
|
||||||
|
dataSource {
|
||||||
|
type=INMEMORY
|
||||||
|
users=[
|
||||||
|
{
|
||||||
|
password=${RPC_PASSWORD}
|
||||||
|
permissions=[
|
||||||
|
ALL
|
||||||
|
]
|
||||||
|
user=rpcUser
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
networkServices : {
|
||||||
|
doormanURL = ${DOORMAN_URL}
|
||||||
|
networkMapURL = ${NETWORKMAP_URL}
|
||||||
|
}
|
||||||
|
|
||||||
|
detectPublicIp = false
|
||||||
|
dataSourceProperties {
|
||||||
|
dataSource {
|
||||||
|
password=${DB_PASSWORD}
|
||||||
|
url="jdbc:h2:file:/opt/corda/persistence/persistence;DB_CLOSE_ON_EXIT=FALSE;WRITE_DELAY=0;LOCK_TIMEOUT=10000"
|
||||||
|
user="sa"
|
||||||
|
}
|
||||||
|
dataSourceClassName="org.h2.jdbcx.JdbcDataSource"
|
||||||
|
}
|
||||||
|
|
||||||
|
emailAddress = ${MY_EMAIL_ADDRESS}
|
70
docker/src/docker/Dockerfile
Normal file
70
docker/src/docker/Dockerfile
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
FROM azul/zulu-openjdk:8u192
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get -y upgrade && apt-get -y install bash curl unzip
|
||||||
|
|
||||||
|
# Create dirs
|
||||||
|
RUN mkdir -p /opt/corda/cordapps
|
||||||
|
RUN mkdir -p /opt/corda/persistence
|
||||||
|
RUN mkdir -p /opt/corda/certificates
|
||||||
|
RUN mkdir -p /opt/corda/drivers
|
||||||
|
RUN mkdir -p /opt/corda/logs
|
||||||
|
RUN mkdir -p /opt/corda/bin
|
||||||
|
RUN mkdir -p /opt/corda/additional-node-infos
|
||||||
|
RUN mkdir -p /etc/corda
|
||||||
|
|
||||||
|
# Create corda user
|
||||||
|
RUN addgroup corda && \
|
||||||
|
useradd corda -g corda -m -d /opt/corda
|
||||||
|
|
||||||
|
WORKDIR /opt/corda
|
||||||
|
|
||||||
|
ENV CORDAPPS_FOLDER="/opt/corda/cordapps"
|
||||||
|
ENV PERSISTENCE_FOLDER="/opt/corda/persistence"
|
||||||
|
ENV CERTIFICATES_FOLDER="/opt/corda/certificates"
|
||||||
|
ENV DRIVERS_FOLDER="/opt/corda/drivers"
|
||||||
|
ENV CONFIG_FOLDER="/etc/corda"
|
||||||
|
|
||||||
|
ENV MY_P2P_PORT=10200
|
||||||
|
ENV MY_RPC_PORT=10201
|
||||||
|
ENV MY_RPC_ADMIN_PORT=10202
|
||||||
|
|
||||||
|
RUN chown -R corda:corda /opt/corda
|
||||||
|
RUN chown -R corda:corda /etc/corda
|
||||||
|
|
||||||
|
##CORDAPPS FOLDER
|
||||||
|
VOLUME ["/opt/corda/cordapps"]
|
||||||
|
##PERSISTENCE FOLDER
|
||||||
|
VOLUME ["/opt/corda/persistence"]
|
||||||
|
##CERTS FOLDER
|
||||||
|
VOLUME ["/opt/corda/certificates"]
|
||||||
|
##OPTIONAL JDBC DRIVERS FOLDER
|
||||||
|
VOLUME ["/opt/corda/drivers"]
|
||||||
|
##LOG FOLDER
|
||||||
|
VOLUME ["/opt/corda/logs"]
|
||||||
|
##ADDITIONAL NODE INFOS FOLDER
|
||||||
|
VOLUME ["/opt/corda/additional-node-infos"]
|
||||||
|
##CONFIG LOCATION
|
||||||
|
VOLUME ["/etc/corda"]
|
||||||
|
|
||||||
|
|
||||||
|
##CORDA JAR
|
||||||
|
ADD --chown=corda:corda corda.jar /opt/corda/bin/corda.jar
|
||||||
|
##CONFIG MANIPULATOR JAR
|
||||||
|
ADD --chown=corda:corda config-exporter.jar /opt/corda/config-exporter.jar
|
||||||
|
##CONFIG GENERATOR SHELL SCRIPT
|
||||||
|
ADD --chown=corda:corda generate-config.sh /opt/corda/bin/config-generator
|
||||||
|
##CORDA RUN SCRIPT
|
||||||
|
ADD --chown=corda:corda run-corda.sh /opt/corda/bin/run-corda
|
||||||
|
##BASE CONFIG FOR GENERATOR
|
||||||
|
ADD --chown=corda:corda starting-node.conf /opt/corda/starting-node.conf
|
||||||
|
##SET EXECUTABLE PERMISSIONS
|
||||||
|
RUN chmod +x /opt/corda/bin/config-generator
|
||||||
|
RUN chmod +x /opt/corda/bin/run-corda
|
||||||
|
|
||||||
|
ENV PATH=$PATH:/opt/corda/bin
|
||||||
|
|
||||||
|
EXPOSE $MY_P2P_PORT
|
||||||
|
EXPOSE $MY_RPC_PORT
|
||||||
|
|
||||||
|
USER "corda"
|
||||||
|
CMD ["run-corda"]
|
84
docker/src/main/kotlin/net.corda.core/ConfigExporter.kt
Normal file
84
docker/src/main/kotlin/net.corda.core/ConfigExporter.kt
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
@file:JvmName("ConfigExporterMain")
|
||||||
|
|
||||||
|
package net.corda.core
|
||||||
|
|
||||||
|
import com.typesafe.config.Config
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
|
import com.typesafe.config.ConfigRenderOptions
|
||||||
|
import com.typesafe.config.ConfigValueFactory
|
||||||
|
import net.corda.common.configuration.parsing.internal.Configuration
|
||||||
|
import net.corda.common.validation.internal.Validated
|
||||||
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
|
import net.corda.node.services.config.parseAsNodeConfiguration
|
||||||
|
import net.corda.nodeapi.internal.config.toConfig
|
||||||
|
import net.corda.nodeapi.internal.config.toConfigValue
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ConfigExporter {
|
||||||
|
fun combineTestNetWithOurConfig(testNetConf: String, ourConf: String, outputFile: String) {
|
||||||
|
var ourParsedConfig = ConfigFactory.parseFile(File(ourConf))
|
||||||
|
val testNetParsedConfig = ConfigFactory.parseFile(File(testNetConf))
|
||||||
|
ourParsedConfig = ourParsedConfig.withValue("keyStorePassword", testNetParsedConfig.getValue("keyStorePassword"))
|
||||||
|
ourParsedConfig = ourParsedConfig.withValue("myLegalName", testNetParsedConfig.getValue("myLegalName"))
|
||||||
|
ourParsedConfig = ourParsedConfig.withValue("trustStorePassword", testNetParsedConfig.getValue("trustStorePassword"))
|
||||||
|
ourParsedConfig = ourParsedConfig.withValue("emailAddress", testNetParsedConfig.getValue("emailAddress"))
|
||||||
|
File(outputFile).writer().use { fileWriter ->
|
||||||
|
val finalConfig = ourParsedConfig.parseAsNodeConfigWithFallback().value().toConfig()
|
||||||
|
var configToWrite = ConfigFactory.empty()
|
||||||
|
ourParsedConfig.entrySet().sortedBy { it.key }.forEach { configEntry ->
|
||||||
|
//use all keys present in "ourConfig" but get values from "finalConfig"
|
||||||
|
val keyWithoutQuotes = configEntry.key.replace("\"", "")
|
||||||
|
println("creating config key: $keyWithoutQuotes with value: ${finalConfig.getValue(keyWithoutQuotes)}")
|
||||||
|
configToWrite = configToWrite.withValue(keyWithoutQuotes, finalConfig.getValue(keyWithoutQuotes))
|
||||||
|
}
|
||||||
|
fileWriter.write(configToWrite.root().render(ConfigRenderOptions.concise().setFormatted(true).setJson(false)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildGenericCZConfig(ourConf: String, outputFile: String){
|
||||||
|
val ourParsedConfig = ConfigFactory.parseFile(File(ourConf))
|
||||||
|
File(outputFile).writer().use { fileWriter ->
|
||||||
|
val finalConfig = ourParsedConfig.parseAsNodeConfigWithFallback().value().toConfig()
|
||||||
|
var configToWrite = ConfigFactory.empty()
|
||||||
|
ourParsedConfig.entrySet().sortedBy { it.key }.forEach { configEntry ->
|
||||||
|
//use all keys present in "ourConfig" but get values from "finalConfig"
|
||||||
|
val keyWithoutQuotes = configEntry.key.replace("\"", "")
|
||||||
|
println("creating config key: $keyWithoutQuotes with value: ${finalConfig.getValue(keyWithoutQuotes)}")
|
||||||
|
configToWrite = configToWrite.withValue(keyWithoutQuotes, finalConfig.getValue(keyWithoutQuotes))
|
||||||
|
}
|
||||||
|
fileWriter.write(configToWrite.root().render(ConfigRenderOptions.concise().setFormatted(true).setJson(false)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Config.parseAsNodeConfigWithFallback(): Validated<NodeConfiguration, Configuration.Validation.Error> {
|
||||||
|
val referenceConfig = ConfigFactory.parseResources("reference.conf")
|
||||||
|
val nodeConfig = this
|
||||||
|
.withValue("baseDirectory", ConfigValueFactory.fromAnyRef("/opt/corda"))
|
||||||
|
.withFallback(referenceConfig)
|
||||||
|
.resolve()
|
||||||
|
return nodeConfig.parseAsNodeConfiguration()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val configExporter = ConfigExporter()
|
||||||
|
|
||||||
|
val command = args[0]
|
||||||
|
|
||||||
|
when (command) {
|
||||||
|
"TEST-NET-COMBINE" -> {
|
||||||
|
val testNetConf = args[1]
|
||||||
|
val ourConf = args[2]
|
||||||
|
val outputFile = args[3]
|
||||||
|
configExporter.combineTestNetWithOurConfig(testNetConf, ourConf, outputFile)
|
||||||
|
}
|
||||||
|
"GENERIC-CZ" -> {
|
||||||
|
val ourConf = args[1]
|
||||||
|
val outputFile = args[2]
|
||||||
|
configExporter.buildGenericCZConfig(ourConf, outputFile)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
throw IllegalArgumentException("Unknown command: $command")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ CorDapps
|
|||||||
upgrade-notes
|
upgrade-notes
|
||||||
upgrading-cordapps
|
upgrading-cordapps
|
||||||
secure-coding-guidelines
|
secure-coding-guidelines
|
||||||
|
flow-overriding
|
||||||
corda-api
|
corda-api
|
||||||
flow-cookbook
|
flow-cookbook
|
||||||
cheat-sheet
|
cheat-sheet
|
||||||
|
@ -6,6 +6,7 @@ Nodes
|
|||||||
|
|
||||||
node-structure
|
node-structure
|
||||||
generating-a-node
|
generating-a-node
|
||||||
|
docker-image
|
||||||
running-a-node
|
running-a-node
|
||||||
deploying-a-node
|
deploying-a-node
|
||||||
corda-configuration-file
|
corda-configuration-file
|
||||||
|
163
docs/source/docker-image.rst
Normal file
163
docs/source/docker-image.rst
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
Official Corda Docker Image
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Running a Node connected to a Compatibility Zone in Docker
|
||||||
|
----------------------------------------------------------
|
||||||
|
|
||||||
|
.. note:: Requirements: A valid node.conf and a valid set of certificates - (signed by the CZ)
|
||||||
|
|
||||||
|
In this example, the certificates are stored at ``/home/user/cordaBase/certificates``, the node configuration is in ``/home/user/cordaBase/config/node.conf`` and the CorDapps to run are in ``/home/TeamCityOutput/cordapps``
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
docker run -ti \
|
||||||
|
--memory=2048m \
|
||||||
|
--cpus=2 \
|
||||||
|
-v /home/user/cordaBase/config:/etc/corda \
|
||||||
|
-v /home/user/cordaBase/certificates:/opt/corda/certificates \
|
||||||
|
-v /home/user/cordaBase/persistence:/opt/corda/persistence \
|
||||||
|
-v /home/user/cordaBase/logs:/opt/corda/logs \
|
||||||
|
-v /home/TeamCityOutput/cordapps:/opt/corda/cordapps \
|
||||||
|
-p 10200:10200 \
|
||||||
|
-p 10201:10201 \
|
||||||
|
corda/corda-4.0-snapshot:latest
|
||||||
|
|
||||||
|
As the node runs within a container, several mount points are required
|
||||||
|
|
||||||
|
1. CorDapps - CorDapps must be mounted at location ``/opt/corda/cordapps``
|
||||||
|
2. Certificates - certificates must be mounted at location ``/opt/corda/certificates``
|
||||||
|
3. Config - the node config must be mounted at location ``/etc/corda/node.config``
|
||||||
|
4. Logging - all log files will be written to location ``/opt/corda/logs``
|
||||||
|
|
||||||
|
If using the H2 database
|
||||||
|
|
||||||
|
5. Persistence - the folder to hold the H2 database files must be mounted at location ``/opt/corda/persistence``
|
||||||
|
|
||||||
|
Running a Node connected to a Bootstrapped Network
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
.. note:: Requirements: A valid node.conf, a valid set of certificates, and an existing network-parameters file
|
||||||
|
|
||||||
|
In this example, we have previously generated a network-parameters file using the bootstrapper tool, which is stored at ``/home/user/sharedFolder/network-parameters``
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
docker run -ti \
|
||||||
|
--memory=2048m \
|
||||||
|
--cpus=2 \
|
||||||
|
-v /home/user/cordaBase/config:/etc/corda \
|
||||||
|
-v /home/user/cordaBase/certificates:/opt/corda/certificates \
|
||||||
|
-v /home/user/cordaBase/persistence:/opt/corda/persistence \
|
||||||
|
-v /home/user/cordaBase/logs:/opt/corda/logs \
|
||||||
|
-v /home/TeamCityOutput/cordapps:/opt/corda/cordapps \
|
||||||
|
-v /home/user/sharedFolder/node-infos:/opt/corda/additional-node-infos \
|
||||||
|
-v /home/user/sharedFolder/network-parameters:/opt/corda/network-parameters \
|
||||||
|
-p 10200:10200 \
|
||||||
|
-p 10201:10201 \
|
||||||
|
corda/corda-4.0-snapshot:latest
|
||||||
|
|
||||||
|
There is a new mount ``/home/user/sharedFolder/node-infos:/opt/corda/additional-node-infos`` which is used to hold the ``nodeInfo`` of all the nodes within the network.
|
||||||
|
As the node within the container starts up, it will place it's own nodeInfo into this directory. This will allow other nodes also using this folder to see this new node.
|
||||||
|
|
||||||
|
|
||||||
|
Generating Configs and Certificates
|
||||||
|
===================================
|
||||||
|
|
||||||
|
It is possible to utilize the image to automatically generate a sensible minimal configuration for joining an existing Corda network.
|
||||||
|
|
||||||
|
Joining TestNet
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. note:: Requirements: A valid registration for TestNet and a one-time code for joining TestNet.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
docker run -ti \
|
||||||
|
-e MY_PUBLIC_ADDRESS="corda-node.example.com" \
|
||||||
|
-e ONE_TIME_DOWNLOAD_KEY="bbcb189e-9e4f-4b27-96db-134e8f592785" \
|
||||||
|
-e LOCALITY="London" -e COUNTRY="GB" \
|
||||||
|
-v /home/user/docker/config:/etc/corda \
|
||||||
|
-v /home/user/docker/certificates:/opt/corda/certificates \
|
||||||
|
corda/corda-4.0-snapshot:latest config-generator --testnet
|
||||||
|
|
||||||
|
``$MY_PUBLIC_ADDRESS`` will be the public address that this node will be advertised on.
|
||||||
|
``$ONE_TIME_DOWNLOAD_KEY`` is the one-time code provided for joining TestNet.
|
||||||
|
``$LOCALITY`` and ``$COUNTRY`` must be set to the values provided when joining TestNet.
|
||||||
|
|
||||||
|
When the container has finished executing ``config-generator`` the following will be true
|
||||||
|
|
||||||
|
1. A skeleton, but sensible minimum node.conf is present in ``/home/user/docker/config``
|
||||||
|
2. A set of certificates signed by TestNet in ``/home/user/docker/certificates``
|
||||||
|
|
||||||
|
It is now possible to start the node using the generated config and certificates
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
docker run -ti \
|
||||||
|
--memory=2048m \
|
||||||
|
--cpus=2 \
|
||||||
|
-v /home/user/docker/config:/etc/corda \
|
||||||
|
-v /home/user/docker/certificates:/opt/corda/certificates \
|
||||||
|
-v /home/user/docker/persistence:/opt/corda/persistence \
|
||||||
|
-v /home/user/docker/logs:/opt/corda/logs \
|
||||||
|
-v /home/user/corda/samples/bank-of-corda-demo/build/nodes/BankOfCorda/cordapps:/opt/corda/cordapps \
|
||||||
|
-p 10200:10200 \
|
||||||
|
-p 10201:10201 \
|
||||||
|
corda/corda-4.0-snapshot:latest
|
||||||
|
|
||||||
|
|
||||||
|
Joining An Existing Compatibility Zone
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
.. note:: Requirements: A Compatibility Zone, the Zone Trust Root and authorisation to join said Zone.
|
||||||
|
|
||||||
|
It is possible to use the image to automate the process of joining an existing Zone as detailed `here <joining-a-compatibility-zone.html#connecting-to-a-compatibility-zone>`__
|
||||||
|
|
||||||
|
The first step is to obtain the Zone Trust Root, and place it within a directory. In the below example, the Trust Root is stored at ``/home/user/docker/certificates/network-root-truststore.jks``.
|
||||||
|
It is possible to configure the name of the Trust Root file by setting the ``TRUST_STORE_NAME`` environment variable in the container.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
docker run -ti --net="host" \
|
||||||
|
-e MY_LEGAL_NAME="O=EXAMPLE,L=Berlin,C=DE" \
|
||||||
|
-e MY_PUBLIC_ADDRESS="corda.example-hoster.com" \
|
||||||
|
-e NETWORKMAP_URL="https://map.corda.example.com" \
|
||||||
|
-e DOORMAN_URL="https://doorman.corda.example.com" \
|
||||||
|
-e NETWORK_TRUST_PASSWORD="trustPass" \
|
||||||
|
-e MY_EMAIL_ADDRESS="cordauser@r3.com" \
|
||||||
|
-v /home/user/docker/config:/etc/corda \
|
||||||
|
-v /home/user/docker/certificates:/opt/corda/certificates \
|
||||||
|
corda/corda-4.0-snapshot:latest config-generator --generic
|
||||||
|
|
||||||
|
|
||||||
|
Several environment variables must also be passed to the container to allow it to register:
|
||||||
|
|
||||||
|
1. ``MY_LEGAL_NAME`` - The X500 to use when generating the config. This must be the same as registered with the Zone.
|
||||||
|
2. ``MY_PUBLIC_ADDRESS`` - The public address to advertise the node on.
|
||||||
|
3. ``NETWORKMAP_URL`` - The address of the Zone's network map service (this should be provided to you by the Zone).
|
||||||
|
4. ``DOORMAN_URL`` - The address of the Zone's doorman service (this should be provided to you by the Zone).
|
||||||
|
5. ``NETWORK_TRUST_PASSWORD`` - The password to the Zone Trust Root (this should be provided to you by the Zone).
|
||||||
|
6. ``MY_EMAIL_ADDRESS`` - The email address to use when generating the config. This must be the same as registered with the Zone.
|
||||||
|
|
||||||
|
There are some optional variables which allow customisation of the generated config:
|
||||||
|
|
||||||
|
1. ``MY_P2P_PORT`` - The port to advertise the node on (defaults to 10200). If changed, ensure the container is launched with the correct published ports.
|
||||||
|
2. ``MY_RPC_PORT`` - The port to open for RPC connections to the node (defaults to 10201). If changed, ensure the container is launched with the correct published ports.
|
||||||
|
|
||||||
|
Once the container has finished performing the initial registration, the node can be started as normal
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
docker run -ti \
|
||||||
|
--memory=2048m \
|
||||||
|
--cpus=2 \
|
||||||
|
-v /home/user/docker/config:/etc/corda \
|
||||||
|
-v /home/user/docker/certificates:/opt/corda/certificates \
|
||||||
|
-v /home/user/docker/persistence:/opt/corda/persistence \
|
||||||
|
-v /home/user/docker/logs:/opt/corda/logs \
|
||||||
|
-v /home/user/corda/samples/bank-of-corda-demo/build/nodes/BankOfCorda/cordapps:/opt/corda/cordapps \
|
||||||
|
-p 10200:10200 \
|
||||||
|
-p 10201:10201 \
|
||||||
|
corda/corda-4.0-snapshot:latest
|
||||||
|
|
@ -14,6 +14,7 @@ include 'client:jfx'
|
|||||||
include 'client:mock'
|
include 'client:mock'
|
||||||
include 'client:rpc'
|
include 'client:rpc'
|
||||||
include 'djvm'
|
include 'djvm'
|
||||||
|
include 'docker'
|
||||||
include 'djvm:cli'
|
include 'djvm:cli'
|
||||||
include 'webserver'
|
include 'webserver'
|
||||||
include 'webserver:webcapsule'
|
include 'webserver:webcapsule'
|
||||||
|
Loading…
Reference in New Issue
Block a user