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:
@@ -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
|
||||
|
||||
19
spring-cloud-stream-module-launcher/docker-compose.yml
Normal file
19
spring-cloud-stream-module-launcher/docker-compose.yml
Normal 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
|
||||
|
||||
@@ -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 .
|
||||
@@ -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>
|
||||
|
||||
@@ -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"]
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
4
spring-cloud-stream-samples/docker-compose.yml
Normal file
4
spring-cloud-stream-samples/docker-compose.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- "6379:6379"
|
||||
Reference in New Issue
Block a user