Align dockerization process with spring.io guides

(And with existing Spring Cloud projects.) Uses a maven plugin to
build the image. It can be pushed manually, or else using
-Ddocker.image.prefix=<path_to_repo>. Removes some of the hard-coded
host names and stuff that came with the old version.
This commit is contained in:
Dave Syer
2015-08-11 09:30:02 +01:00
parent 818ad6e3e8
commit e81ed1eace
10 changed files with 96 additions and 72 deletions

View File

@@ -13,7 +13,7 @@ mvn -s .settings.xml package
cd ..
````
2: start redis locally via `redis-server` (optionally start `redis-cli` and use the `MONITOR` command to watch activity)
2: start redis locally via `redis-server` or `docker-compose` (there's a `docker-compose.yml` in `spring-cloud-stream-samples`). Optionally start `redis-cli` and use the `MONITOR` command to watch activity.
*NOTE:* redis.conf (on OSX it is found here: /usr/local/etc/redis.conf) may need to be updated to set the binding to an address other than 127.0.0.1 else the docker instances will fail to connect. For example: bind 0.0.0.0
@@ -38,7 +38,18 @@ The time messages will be emitted every 5 seconds. The console for the log modul
## Running with Docker
Run each module as a Docker process by passing environment variables for the module name as well as the host machine's IP address for the redis connection to be established within the container:
The easiest way to get a demo working is to use `docker-compose` (from this directory):
```
$ mvn package docker:build
$ docker-compose up
...
logsink_1 | 2015-08-11 08:25:49.909 INFO 1 --- [hannel-adapter1] o.s.cloud.stream.module.log.LogSink : Received: 2015-08-11 08:25:49
logsink_1 | 2015-08-11 08:25:54.909 INFO 1 --- [hannel-adapter1] o.s.cloud.stream.module.log.Log
...
```
You can also run each module individually as a Docker process by passing environment variables for the module name as well as the host machine's IP address for the redis connection to be established within the container:
````
docker run -p 8080:8080 -e MODULES=org.springframework.cloud.stream.module:time-source:1.0.0.BUILD-SNAPSHOT -e SPRING_REDIS_HOST=<host.ip> springcloud/stream-module-launcher

View File

@@ -0,0 +1,19 @@
redis:
image: redis
timesource:
image: springcloud/stream-module-launcher
links:
- redis
environment:
SPRING_REDIS_HOST: redis
MODULES: org.springframework.cloud.stream.module:time-source:1.0.0.BUILD-SNAPSHOT
logsink:
image: springcloud/stream-module-launcher
links:
- redis
environment:
SPRING_REDIS_HOST: redis
MODULES: org.springframework.cloud.stream.module:log-sink:1.0.0.BUILD-SNAPSHOT

View File

@@ -1,13 +0,0 @@
#!/bin/bash
if [ ! -f "Dockerfile" ]; then
echo "Dockerfile not found"
exit 1
fi
if [ ! -f "target/spring-cloud-stream-module-launcher-1.0.0.BUILD-SNAPSHOT-exec.jar" ]; then
echo "JAR not available; run mvn package first"
exit 1
fi
docker build -t 192.168.59.103:5000/module-launcher .

View File

@@ -20,16 +20,19 @@
<aether.version>1.0.2.v20150114</aether.version>
<maven.version>3.1.0</maven.version>
<wiremock.version>1.57</wiremock.version>
<docker.image.prefix>springcloud</docker.image.prefix>
<docker.image.name>stream-module-launcher</docker.image.name>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -68,12 +71,6 @@
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-test</artifactId>
<version>${spring-integration.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
@@ -137,6 +134,22 @@
<classifier>exec</classifier>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.2.3</version>
<configuration>
<imageName>${docker.image.prefix}/${docker.image.name}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}-exec.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,5 +1,5 @@
FROM java:8
VOLUME /tmp
ADD target/spring-cloud-stream-module-launcher-1.0.0.BUILD-SNAPSHOT-exec.jar module-launcher.jar
ADD *-exec.jar module-launcher.jar
RUN bash -c 'touch /module-launcher.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/module-launcher.jar"]

View File

@@ -18,11 +18,7 @@ package org.springframework.boot.loader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.springframework.boot.loader.archive.Archive;
import org.springframework.boot.loader.util.AsciiBytes;
@@ -30,8 +26,8 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* A (possibly temporary) alternative to {@link JarLauncher} that provides a
* public {@link #launch(String[])} method.
* A (possibly temporary) alternative to {@link JarLauncher} that provides a public
* {@link #launch(String[])} method.
*
* @author Mark Fisher
* @author Marius Bogoevici
@@ -60,14 +56,19 @@ public class ModuleJarLauncher extends ExecutableArchiveLauncher {
}
@Override
protected void launch(String[] args, String mainClass, ClassLoader classLoader) throws Exception {
try {
// disable JVM-wide registration of TomcatURLStreamHandlerFactory
Class<?> streamHandlerFactoryClass = ClassUtils.forName("org.apache.catalina.webresources.TomcatURLStreamHandlerFactory", classLoader);
Method disable = ReflectionUtils.findMethod(streamHandlerFactoryClass, "disable");
ReflectionUtils.invokeMethod(disable, null);
} catch (ClassNotFoundException e) {
// ignore
protected void launch(String[] args, String mainClass, ClassLoader classLoader)
throws Exception {
if (ClassUtils.isPresent(
"org.apache.catalina.webresources.TomcatURLStreamHandlerFactory",
classLoader)) {
// Ensure the method is invoked on a class that is loaded by the provided
// class loader (not the current context class loader):
Method method = ReflectionUtils
.findMethod(
classLoader
.loadClass("org.apache.catalina.webresources.TomcatURLStreamHandlerFactory"),
"disable");
ReflectionUtils.invokeMethod(method, null);
}
super.launch(args, mainClass, classLoader);
}

View File

@@ -16,33 +16,23 @@
package org.springframework.cloud.stream.module.launcher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
/**
* Bootstrap for launching one or more modules, provided via the "modules" system property or "MODULES" environment variable as a comma-delimited list, with the arguments provided at
* launch.
* Bootstrap for launching one or more modules, provided via the "modules" system property
* or "MODULES" environment variable as a comma-delimited list, with the arguments
* provided at launch.
*
* @see ModuleLauncher#launch(String[], String[]) for module and argument structure and format
* @see ModuleLauncher#launch(String[], String[]) for module and argument structure and
* format
*
* @author Marius Bogoevici
*/
@SpringBootApplication
@ComponentScan(basePackageClasses = ModuleLauncherApplication.class)
public class ModuleLauncherApplication {
private static final Log log = LogFactory.getLog(ModuleLauncherApplication.class);
public static void main(String[] args) throws Exception {
try {
SpringApplication.run(ModuleLauncherApplication.class, args);
}
catch (Exception e) {
log.error("Failed to launch module ", e);
}
SpringApplication.run(ModuleLauncherApplication.class, args);
}
}

View File

@@ -19,11 +19,6 @@ package org.springframework.cloud.stream.module.launcher;
import java.io.File;
import java.util.Collections;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.stream.module.resolver.AetherModuleResolver;
@@ -36,10 +31,11 @@ import org.springframework.context.annotation.Configuration;
*/
@Configuration
@ConfigurationProperties
// TODO: use a prefix
public class ModuleLauncherConfiguration {
public static final String DEFAULT_LOCAL_REPO =
System.getProperty("user.home") + File.separator + ".m2" + File.separator + "repository";
public static final String DEFAULT_LOCAL_REPO = System.getProperty("user.home")
+ File.separator + ".m2" + File.separator + "repository";
public static final String DEFAULT_REMOTE_REPO = "https://repo.spring.io/libs-snapshot";
@@ -61,7 +57,8 @@ public class ModuleLauncherConfiguration {
@Bean
@ConditionalOnMissingBean(ModuleResolver.class)
public ModuleResolver moduleResolver() {
return new AetherModuleResolver(localRepository, Collections.singletonMap("remoteRepository", remoteRepository));
return new AetherModuleResolver(this.localRepository, Collections.singletonMap(
"remoteRepository", this.remoteRepository));
}
@Bean

View File

@@ -18,8 +18,6 @@ package org.springframework.cloud.stream.module.launcher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
@@ -34,6 +32,7 @@ import org.springframework.util.StringUtils;
*/
@Component
@ConfigurationProperties
// TODO: use a prefix
public class ModuleLauncherRunner implements ApplicationRunner, InitializingBean {
private final static Log log = LogFactory.getLog(ModuleLauncherRunner.class);
@@ -41,24 +40,27 @@ public class ModuleLauncherRunner implements ApplicationRunner, InitializingBean
@Autowired
private ModuleLauncher moduleLauncher;
private String modules;
private String[] modules;
public void setModules(String modules) {
public void setModules(String[] modules) {
this.modules = modules;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.hasText(modules, "A list of modules must be specified");
Assert.notEmpty(this.modules, "A list of modules must be specified");
}
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
String[] launchedModules = modules.split(",");
String[] launchedModules = this.modules;
if (log.isInfoEnabled()) {
log.info("Launching: " + modules + " with arguments: "
+ StringUtils.arrayToCommaDelimitedString(applicationArguments.getSourceArgs()));
log.info("Launching: "
+ StringUtils.arrayToCommaDelimitedString(this.modules)
+ " with arguments: "
+ StringUtils.arrayToCommaDelimitedString(applicationArguments
.getSourceArgs()));
}
moduleLauncher.launch(launchedModules, applicationArguments.getSourceArgs());
this.moduleLauncher.launch(launchedModules, applicationArguments.getSourceArgs());
}
}

View File

@@ -0,0 +1,4 @@
redis:
image: redis
ports:
- "6379:6379"