├── .gitignore ├── README.md ├── base-image ├── Dockerfile ├── build.gradle └── start_java.sh ├── build.gradle ├── docker-compose.yml ├── docker-compose_cpu_quota.yml ├── docker-compose_cpu_sets.yml ├── docker-compose_cpu_shares.yml ├── dropwizard-app ├── build.gradle ├── docker │ ├── .gitignore │ ├── Dockerfile │ └── config.yml ├── gradlew ├── gradlew.bat └── src │ └── main │ └── java │ └── info │ └── batey │ └── djvm │ ├── Config.java │ ├── ExampleApplication.java │ └── Service.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── ratpack-app ├── .dockerignore ├── README.md ├── build.gradle ├── docker │ ├── .gitignore │ └── Dockerfile ├── gradlew.bat └── src │ └── main │ └── java │ └── info │ └── batey │ └── djvm │ ├── Db.java │ └── Main.java ├── settings.gradle ├── tools └── cadvisor.sh ├── wiremock ├── Dockerfile ├── build.gradle ├── mappings │ └── mapping.json └── wiremock-1.57-standalone.jar └── your-own-container ├── .main.go.swp ├── README.md └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | target 3 | build 4 | .gradle 5 | *.iml 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Add Running a JVM in Docker, a good idea? 2 | 3 | ## Intro 4 | 5 | This is a set of resources for understanding the complexities of running your JVM based application inside a 6 | linux container, specifically Docker. 7 | 8 | I'm doing a talk at the following conferences based on this material: 9 | * Geecon 2016 10 | * Devoxx UK 2016 11 | * Devoxx Poland 2016 12 | 13 | ### Motivation 14 | 15 | Why do we want to run our application inside containers? 16 | 17 | * Multi tenancy 18 | * Consistent deployment format across technology stacks 19 | * Access to orchestration tools: 20 | * Kubernetes 21 | * Marathon on Mesos 22 | * Using docker for other purposes: CI, dev dependencies 23 | 24 | ### Deployment options 25 | 26 | * Traditional JEE/servelet container: WebSphere, Tomcat running on bare metal 27 | * Executable jars with embedded Jetty running on bare metal 28 | * A traditional container inside Docker? Why? 29 | * Executable jar inside linux container - the sweet spot 30 | 31 | 32 | ### Cost savings 33 | 34 | // TODO: Show number of servers for single vs VMs vs Kubernetes 35 | 36 | ## What 37 | 38 | The best way to work with Docker is to learn a small amount about the underlying 39 | kernel features. 40 | 41 | ### Namespaces 42 | 43 | Containers are built on top of Linux namespaces. Giving processes their own PID 44 | namespace, mounts 45 | 46 | #### PID 47 | 48 | TODO: 49 | * Demo PS inside and outside of the container. 50 | 51 | #### Mount 52 | 53 | TODO: 54 | * Show mounts inside and outside of a container. Show outside where the ones 55 | inside map to. 56 | 57 | #### Layered file systems 58 | 59 | #### Users 60 | 61 | TODO: 62 | * Show uids inside and outside of the container. 63 | 64 | ### CGroups 65 | 66 | In addition to namepsaces running containers are restricted via CGroups to the 67 | amount of memory and CPU they use. 68 | 69 | TODO: 70 | * Show a container with `systemd-cfls` then `systemd-cgtop` then put some 71 | load and how that cgroup grow. 72 | 73 | #### Docker access to CGroups 74 | 75 | TODO: 76 | * Show options that can be passed to Docker run vs settings on cgroups. 77 | 78 | * `memory` 79 | * `memory--swap` 80 | * `memory-soft-limit` 81 | * `oom-kill-disable` (Show a java process with this on and not on) 82 | 83 | * `cpu-shares` 84 | * `cpuset-cpu` 85 | * `cpu-mems` (for NUMA) 86 | 87 | TODO: Show kubernetes docs about squashable resources 88 | 89 | 90 | ## Tools> 91 | 92 | Top 93 | Htop 94 | Free 95 | // Cotnainer breakdown 96 | systemd-{cgtop, cgls} 97 | // See namespaces for a process 98 | 99 | CAdvisor 100 | 101 | ## Examples 102 | 103 | Scenario: to get 1000 TPS for a container. 104 | 105 | The logic inside the app containers one HTTP call and one Database call. 106 | 107 | Goal is to make our container as small as possible. 108 | 109 | Areas to investigate: 110 | * Memory usage 111 | * Tuning threads 112 | 113 | TODO 114 | * Count number of threads 115 | 116 | ### Thread per request 117 | 118 | A lot of Java web frameworks, Servlets included, use the thread per request execution model. 119 | 120 | // TODO Picture of a pool of threads 121 | 122 | The popular Jetty servlet container is one such library. Dropwizard is a framework 123 | that brings together Jersey with a few other popular libraries. 124 | 125 | #### Dropwizard 126 | 127 | ### Thread per core 128 | 129 | #### Ratpack example 130 | 131 | #### Akka example (Optional) 132 | 133 | ### Demos 134 | 135 | * OOM kill a process with JVM options 136 | * dmesg 137 | * docker logs 138 | * docker restart 139 | 140 | 141 | 142 | TODO: 143 | * Look at the java swiss army knife 144 | -------------------------------------------------------------------------------- /base-image/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM phusion/baseimage 2 | 3 | ENV JAVA_HOME /usr/jdk1.8.0_66 4 | 5 | RUN curl \ 6 | --silent \ 7 | --location \ 8 | --retry 3 \ 9 | --header "Cookie: oraclelicense=accept-securebackup-cookie;" \ 10 | "http://download.oracle.com/otn-pub/java/jdk/8u66-b17/server-jre-8u66-linux-x64.tar.gz" \ 11 | | gunzip \ 12 | | tar x -C /usr/ \ 13 | && ln -s $JAVA_HOME /usr/java \ 14 | && rm -rf $JAVA_HOME/man 15 | 16 | ENV PATH ${PATH}:${JAVA_HOME}/bin 17 | 18 | COPY start_java.sh / 19 | 20 | ENTRYPOINT ["/sbin/my_init", "--"] 21 | -------------------------------------------------------------------------------- /base-image/build.gradle: -------------------------------------------------------------------------------- 1 | task build(type: Exec) { 2 | commandLine 'docker', 'build', '-t', 'java-base-image', '.' 3 | } 4 | -------------------------------------------------------------------------------- /base-image/start_java.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | function usage() { 4 | echo 'Set JAVA_OPTIONS to override parameters passed to java. Excluding any GC related options.' 5 | echo 'Set GC_OPTIONS for any GC related parameters.' 6 | echo 'Usage: start_java.sh -c [command e.g -jar /data/app.jar server config.yml]' 7 | exit 1 8 | } 9 | 10 | #Separated GC because if multiple GCs are passed to the JVM G1 is picked regardless of order 11 | gc=${GC_OPTIONS:-"-XX:+UseG1GC -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps"} 12 | java_options=${JAVA_OPTIONS:-"-Xmx256m -Xms256m"} 13 | other=${CORE_OPTIONS:-"-XX:NativeMemoryTracking=summary -XX:+UnlockDiagnosticVMOptions -XX:+AlwaysPreTouch"} 14 | 15 | while getopts ":c:h" OPTION; do 16 | case $OPTION in 17 | c) 18 | command=$OPTARG 19 | ;; 20 | h) 21 | usage 22 | ;; 23 | :) 24 | echo "Option -$OPTARG requires an argument." >&2 25 | exit 1 26 | ;; 27 | esac 28 | done 29 | 30 | if [ -z "$command" ] 31 | then 32 | usage 33 | fi 34 | 35 | java $other $gc $java_options $command 36 | 37 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | 2 | task wrapper(type: Wrapper) { 3 | gradleVersion = '2.12' 4 | } 5 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | wiremock: 4 | image: wiremock 5 | ports: 6 | - "7070:7070" 7 | 8 | ratpack: 9 | image: ratpack-app 10 | ports: 11 | - "5050:5050" 12 | links: 13 | - wiremock 14 | 15 | dropwizard: 16 | image: dropwizard-app 17 | ports: 18 | - "8080:8080" 19 | links: 20 | - wiremock 21 | -------------------------------------------------------------------------------- /docker-compose_cpu_quota.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | wiremock: 4 | image: wiremock 5 | ports: 6 | - "7070:7070" 7 | cpu_quota: 400000 8 | 9 | ratpack: 10 | image: ratpack-app 11 | ports: 12 | - "5050:5050" 13 | links: 14 | - wiremock 15 | cpu_quota: 100000 16 | 17 | dropwizard: 18 | image: dropwizard-app 19 | ports: 20 | - "8080:8080" 21 | links: 22 | - wiremock 23 | cpu_quota: 100000 24 | -------------------------------------------------------------------------------- /docker-compose_cpu_sets.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | wiremock: 4 | image: wiremock 5 | ports: 6 | - "7070:7070" 7 | cpuset: "8,9,10,11" 8 | 9 | ratpack: 10 | image: ratpack-app 11 | ports: 12 | - "5050:5050" 13 | links: 14 | - wiremock 15 | cpuset: "2" 16 | 17 | dropwizard: 18 | image: dropwizard-app 19 | ports: 20 | - "8080:8080" 21 | links: 22 | - wiremock 23 | cpuset: "1" 24 | -------------------------------------------------------------------------------- /docker-compose_cpu_shares.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | wiremock: 4 | image: wiremock 5 | ports: 6 | - "7070:7070" 7 | cpu_shares: 4096 8 | 9 | ratpack: 10 | image: ratpack-app 11 | ports: 12 | - "5050:5050" 13 | links: 14 | - wiremock 15 | cpu_shares: 1024 16 | 17 | dropwizard: 18 | image: dropwizard-app 19 | ports: 20 | - "8080:8080" 21 | links: 22 | - wiremock 23 | cpu_shares: 1024 24 | -------------------------------------------------------------------------------- /dropwizard-app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | buildscript { 3 | repositories { 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' 9 | 10 | } 11 | } 12 | apply plugin: 'com.github.johnrengelman.shadow' 13 | 14 | jar { 15 | manifest { 16 | attributes 'Main-Class': 'info.batey.djvm.ExampleApplication' 17 | } 18 | } 19 | 20 | shadowJar { 21 | mergeServiceFiles() 22 | exclude 'META-INF/*.DSA' 23 | exclude 'META-INF/*.RSA' 24 | } 25 | 26 | sourceCompatibility = 1.8 27 | 28 | task copyJar(type: Exec, dependsOn: 'shadowJar') { 29 | commandLine 'cp', './build/libs/dropwizard-app-all.jar', './docker/' 30 | } 31 | 32 | task dockerBuild(type: Exec, dependsOn: 'copyJar') { 33 | workingDir './docker' 34 | commandLine 'docker', 'build', '-t', 'dropwizard-app', '.' 35 | } 36 | 37 | build.dependsOn(dockerBuild) 38 | 39 | project.ext { 40 | dropwizardVersion = '0.9.2' 41 | } 42 | 43 | repositories { 44 | mavenCentral() 45 | } 46 | 47 | dependencies { 48 | compile group: 'io.dropwizard', name: 'dropwizard-core', version: dropwizardVersion 49 | compile group: 'io.dropwizard', name: 'dropwizard-client', version: dropwizardVersion 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /dropwizard-app/docker/.gitignore: -------------------------------------------------------------------------------- 1 | *.jar 2 | -------------------------------------------------------------------------------- /dropwizard-app/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java-base-image 2 | 3 | ADD config.yml /data/ 4 | ADD dropwizard-app-all.jar /data/ 5 | 6 | ENV JAVA_OPTIONS="-XX:+PrintGC " 7 | 8 | CMD ["/start_java.sh", "-c", "-jar /data/dropwizard-app-all.jar server /data/config.yml"] 9 | 10 | EXPOSE 8080 11 | -------------------------------------------------------------------------------- /dropwizard-app/docker/config.yml: -------------------------------------------------------------------------------- 1 | server: 2 | # softNofileLimit: 1000 3 | # hardNofileLimit: 1000 4 | minThreads: 1 5 | maxThreads: 5 6 | applicationConnectors: 7 | - type: http 8 | port: 9080 9 | adminConnectors: 10 | - type: http 11 | port: 8081 -------------------------------------------------------------------------------- /dropwizard-app/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /dropwizard-app/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /dropwizard-app/src/main/java/info/batey/djvm/Config.java: -------------------------------------------------------------------------------- 1 | package info.batey.djvm; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import io.dropwizard.Configuration; 5 | import io.dropwizard.client.HttpClientConfiguration; 6 | 7 | import javax.validation.Valid; 8 | import javax.validation.constraints.NotNull; 9 | 10 | public class Config extends Configuration { 11 | 12 | @Valid 13 | @NotNull 14 | @JsonProperty 15 | private HttpClientConfiguration httpClient = new HttpClientConfiguration(); 16 | 17 | public HttpClientConfiguration getHttpClientConfiguration() { 18 | return httpClient; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /dropwizard-app/src/main/java/info/batey/djvm/ExampleApplication.java: -------------------------------------------------------------------------------- 1 | package info.batey.djvm; 2 | 3 | import io.dropwizard.Application; 4 | import io.dropwizard.client.HttpClientBuilder; 5 | import io.dropwizard.setup.Environment; 6 | import org.apache.http.client.HttpClient; 7 | 8 | public class ExampleApplication extends Application { 9 | 10 | public static void main(String[] args) throws Exception { 11 | new ExampleApplication().run(args); 12 | } 13 | 14 | @Override 15 | public void run(Config config, Environment environment) throws Exception { 16 | final HttpClient httpClient = new HttpClientBuilder(environment).using(config.getHttpClientConfiguration()) 17 | .build("http-client"); 18 | environment.jersey().register(new Service(httpClient)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /dropwizard-app/src/main/java/info/batey/djvm/Service.java: -------------------------------------------------------------------------------- 1 | package info.batey.djvm; 2 | 3 | import org.apache.http.client.HttpClient; 4 | import org.apache.http.client.methods.HttpGet; 5 | import org.apache.http.client.methods.HttpPost; 6 | import org.apache.http.util.EntityUtils; 7 | 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import java.io.IOException; 11 | 12 | @Path("/") 13 | public class Service { 14 | 15 | private final HttpClient httpClient; 16 | 17 | public Service(HttpClient httpClient) { 18 | this.httpClient = httpClient; 19 | } 20 | 21 | @GET 22 | @Path("/callout") 23 | public String callout() throws IOException { 24 | HttpGet httpGet = new HttpGet("http://wiremock:7070/name"); 25 | return EntityUtils.toString(httpClient.execute(httpGet).getEntity()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chbatey/docker-jvm-talk/438292b57531101072b39f9d2be5caee484946d9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Apr 28 08:24:28 BST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /ratpack-app/.dockerignore: -------------------------------------------------------------------------------- 1 | build 2 | src 3 | *.iml 4 | .idea 5 | -------------------------------------------------------------------------------- /ratpack-app/README.md: -------------------------------------------------------------------------------- 1 | # Example ratpack application for running in docker 2 | 3 | TODO: 4 | * Add wiremock and a start up gradle task that gets things running 5 | * Add databse call? Do after dropwizard. Add delay via wiremock first. 6 | 7 | ### Threads 8 | 9 | Ratpack compute threads 10 | GC threads 11 | Compiler threads 12 | Other netty threads?? 13 | Favourite DB driver threads 14 | Favourite async HTTP client threads 15 | Favourite sync HTTP client threads 16 | RxJava threads 17 | 18 | ### Memory usage 19 | 20 | Free 21 | Htop 22 | Top 23 | JCmd 24 | HEAP 25 | Metaspace 26 | OOMKilled - show in docker + dmesg 27 | 28 | -------------------------------------------------------------------------------- /ratpack-app/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | 6 | dependencies { 7 | classpath "io.ratpack:ratpack-gradle:1.3.0" 8 | classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' 9 | } 10 | } 11 | 12 | apply plugin: "io.ratpack.ratpack-java" 13 | apply plugin: 'com.github.johnrengelman.shadow' 14 | apply plugin: 'java' 15 | 16 | mainClassName = 'info.batey.djvm.Main' 17 | 18 | dependencies { 19 | compile 'ch.qos.logback:logback-classic:1.1.7' 20 | } 21 | 22 | repositories { 23 | jcenter() 24 | } 25 | 26 | task copyJar(type: Exec, dependsOn: 'shadowJar') { 27 | commandLine 'cp', './build/libs/ratpack-app-all.jar', './docker/' 28 | } 29 | 30 | task dockerBuild(type: Exec, dependsOn: 'copyJar') { 31 | workingDir './docker' 32 | commandLine 'docker', 'build', '-t', 'ratpack-app', '.' 33 | } 34 | 35 | build.dependsOn(dockerBuild) 36 | -------------------------------------------------------------------------------- /ratpack-app/docker/.gitignore: -------------------------------------------------------------------------------- 1 | *.jar 2 | -------------------------------------------------------------------------------- /ratpack-app/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java-base-image 2 | 3 | ADD ratpack-app-all.jar /data/ 4 | 5 | ENV JAVA_OPTIONS="-XX:+PrintGC " 6 | 7 | CMD ["/start_java.sh", "-c", "-jar /data/ratpack-app-all.jar"] 8 | 9 | EXPOSE 5050 10 | -------------------------------------------------------------------------------- /ratpack-app/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /ratpack-app/src/main/java/info/batey/djvm/Db.java: -------------------------------------------------------------------------------- 1 | package info.batey.djvm; 2 | 3 | import ratpack.exec.Promise; 4 | 5 | 6 | public class Db { 7 | Promise getRecord(String name) { 8 | return Promise.value("A DB record:" + name); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ratpack-app/src/main/java/info/batey/djvm/Main.java: -------------------------------------------------------------------------------- 1 | package info.batey.djvm; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import ratpack.exec.Promise; 6 | import ratpack.http.client.HttpClient; 7 | import ratpack.server.RatpackServer; 8 | 9 | import java.net.URI; 10 | 11 | public class Main { 12 | 13 | private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); 14 | 15 | public static void main(String... args) throws Exception { 16 | 17 | Db db = new Db(); 18 | RatpackServer.start(server -> server 19 | .registryOf(rs -> rs.add(db)) 20 | .handlers(chain -> chain 21 | .all(ctx -> { 22 | LOGGER.info("All"); 23 | ctx.next(); 24 | }) 25 | .get("callout", ctx -> { 26 | Db database = ctx.get(Db.class); 27 | 28 | Promise response = ctx.get(HttpClient.class) 29 | .get(new URI("http://wiremock:7070/name")) 30 | .map(r -> r.getBody().getText()); 31 | 32 | Promise withDb = response.flatMap(database::getRecord); 33 | 34 | ctx.render(withDb); 35 | }) 36 | .get(":name", ctx -> ctx.render("Hello " + ctx.getPathTokens().get("name") + "!")) 37 | )); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'base-image' 2 | include 'wiremock' 3 | include 'dropwizard-app' 4 | include 'ratpack-app' 5 | -------------------------------------------------------------------------------- /tools/cadvisor.sh: -------------------------------------------------------------------------------- 1 | docker run \ 2 | --volume=/:/rootfs:ro \ 3 | --volume=/var/run:/var/run:rw \ 4 | --volume=/sys:/sys:ro \ 5 | --volume=/var/lib/docker/:/var/lib/docker:ro \ 6 | --publish=8080:8080 \ 7 | --detach=true \ 8 | --name=cadvisor \ 9 | google/cadvisor:latest 10 | -------------------------------------------------------------------------------- /wiremock/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java-base-image 2 | 3 | ADD ./wiremock-1.57-standalone.jar /data/wiremock.jar 4 | ADD mappings/mapping.json /mappings/mapping.json 5 | 6 | CMD ["/start_java.sh", "-c", "-jar /data/wiremock.jar --port 7070"] 7 | 8 | EXPOSE 7070 9 | -------------------------------------------------------------------------------- /wiremock/build.gradle: -------------------------------------------------------------------------------- 1 | task build(type: Exec) { 2 | commandLine 'docker', 'build', '-t', 'wiremock', '.' 3 | } 4 | -------------------------------------------------------------------------------- /wiremock/mappings/mapping.json: -------------------------------------------------------------------------------- 1 | { 2 | "request": { 3 | "method": "GET", 4 | "url": "/name" 5 | }, 6 | "response": { 7 | "status": 200, 8 | "body": "chris", 9 | "headers": { 10 | "Content-Type": "text/plain" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /wiremock/wiremock-1.57-standalone.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chbatey/docker-jvm-talk/438292b57531101072b39f9d2be5caee484946d9/wiremock/wiremock-1.57-standalone.jar -------------------------------------------------------------------------------- /your-own-container/.main.go.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chbatey/docker-jvm-talk/438292b57531101072b39f9d2be5caee484946d9/your-own-container/.main.go.swp -------------------------------------------------------------------------------- /your-own-container/README.md: -------------------------------------------------------------------------------- 1 | ## Namespaces 2 | 3 | ### PID 4 | 5 | Isolate a process tree. Making the root PID 1. 6 | 7 | TODO: PS from host, go into a container and PS. 8 | 9 | ### MNT 10 | 11 | Have a process tree have its own mount table. Including a different filesystem 12 | that could have a different operating system on. 13 | 14 | ### NET 15 | 16 | Have a process have its own network stack. 17 | 18 | TOOD: Examples of how this works with Rocket and Docker 19 | 20 | ### UTS 21 | 22 | Give a process its own view of the machine's hostname. 23 | 24 | ### IPC 25 | 26 | Inter process communication. 27 | 28 | TODO: Research 29 | 30 | ### User 31 | 32 | Allows mapping of users in the container to different users on the host. Meaning 33 | that inside the container it can appear as root but it is actually mapped to a 34 | non root user on the host. 35 | 36 | ### User 37 | 38 | Allows mapping of users in the container to different users on the host. Meaning 39 | that inside the container it can appear as root but it is actually mapped to a 40 | non root user on the host. 41 | 42 | ## CGroups 43 | 44 | Reosource allocation 45 | 46 | ## Layered file systems 47 | 48 | Effiecent way to copy and shop a containers file system. 49 | 50 | ## Stuff 51 | 52 | -------------------------------------------------------------------------------- /your-own-container/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | "syscall" 8 | ) 9 | 10 | func main() { 11 | switch os.Args[1] { 12 | case "run": 13 | parent() 14 | case "child": 15 | child() 16 | default: 17 | panic("wat should I do") 18 | } 19 | } 20 | 21 | func parent() { 22 | cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...) 23 | cmd.Stdin = os.Stdin 24 | cmd.Stdout = os.Stdout 25 | cmd.Stderr = os.Stderr 26 | 27 | if err := cmd.Run(); err != nil { 28 | fmt.Println("ERROR", err) 29 | os.Exit(1) 30 | } 31 | } 32 | 33 | func child() { 34 | cmd := exec.Command(os.Args[2], os.Args[3:]...) 35 | cmd.Stdin = os.Stdin 36 | cmd.Stdout = os.Stdout 37 | cmd.Stderr = os.Stderr 38 | 39 | if err := cmd.Run(); err != nil { 40 | fmt.Println("ERROR", err) 41 | os.Exit(1) 42 | } 43 | } 44 | 45 | func must(err error) { 46 | if err != nil { 47 | panic(err) 48 | } 49 | } 50 | --------------------------------------------------------------------------------