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
|
||||
upgrading-cordapps
|
||||
secure-coding-guidelines
|
||||
flow-overriding
|
||||
corda-api
|
||||
flow-cookbook
|
||||
cheat-sheet
|
||||
|
@ -6,6 +6,7 @@ Nodes
|
||||
|
||||
node-structure
|
||||
generating-a-node
|
||||
docker-image
|
||||
running-a-node
|
||||
deploying-a-node
|
||||
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:rpc'
|
||||
include 'djvm'
|
||||
include 'docker'
|
||||
include 'djvm:cli'
|
||||
include 'webserver'
|
||||
include 'webserver:webcapsule'
|
||||
|
Loading…
Reference in New Issue
Block a user