Docker学习二(部署一个可以自由获取环境变量的SpringWeb)
来源:互联网 发布:java 两个数组值交换 编辑:程序博客网 时间:2024/06/05 14:27
- 引言
- 环境部署
- Web部署
- 源码展示 非必须
- 开始访问
- Get PortTomcat Only
引言
在 Dokcer学习一 已经可以简单的安装一个Docker 容器并暴露某个端口给外部使用了。
安装不是目的, 应用才是王道。 发布一个快速部署的Web容器才是Docker的用处。
当前有需求:
Tomcat启动在Docker容器中,它需要告知注册中心自己暴露对外的Host以及Port。
传统的方式只可以获取到Tomcat启动时绑定的端口, 需要获取Docker对外映射的宿主机的Host以及开放的端口。
环境部署
应用程序目录:/opt
安装JDK.
# wget http://download.oracle.com/otn-pub/java/jdk/8u91-b14/jdk-8u91-linux-x64.tar.gz# lsjdk-8u91-linux-x64.tar.gz# tar -xzvf jdk-8u91-linux-x64.tar.gz# jdk1.8.0_91/bin/java -versionjava version "1.8.0_91"Java(TM) SE Runtime Environment (build 1.8.0_91-b14)Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
安装Tomcat
# wget http://mirrors.hust.edu.cn/apache/tomcat/tomcat-8/v8.5.0/bin/apache-tomcat-8.5.0.tar.gz# tar -xzvf apache-tomcat-8.5.0.tar.gz # apache-tomcat-8.5.0/bin/startup.sh Using CATALINA_BASE: /opt/apache-tomcat-8.5.0Using CATALINA_HOME: /opt/apache-tomcat-8.5.0Using CATALINA_TMPDIR: /opt/apache-tomcat-8.5.0/tempUsing JRE_HOME: /opt/jdk1.8.0_91Using CLASSPATH: /opt/apache-tomcat-8.5.0/bin/bootstrap.jar:/opt/apache-tomcat-8.5.0/bin/tomcat-juli.jarTomcat started.# curl -I -s 127.0.0.1:8080HTTP/1.1 200
将程序委托给Supervisord管理
# echo '#! /bin/bashexport JAVA_HOME=/opt/jdk1.8.0_91export CLASSPATH=.:$JAVA_HOME:/lib:$JAVA_HOME/jre/lib:export PATH=$PATH:$JAVA_HOME/bin/opt/apache-tomcat-8.5.0/bin/startup.sh' > /etc/supervisor/conf.d/tomcat.sh# echo '[supervisord]nodaemon=true[program:tomcat]command=/etc/supervisor/conf.d/tomcat.sh' > /etc/supervisor/conf.d/tomcat.conf
当然, 每次变更一定要记住提交。
# docker commit acf27ff06413 tomcat
此时就可以开始访问Tomcat服务了。
# docker run -it -d -p 22 -p 8080 tomcat /usr/bin/supervisord# docker ps -aIMAGE STATUS PORTS tomcat Up 6 seconds 0.0.0.0:32774->22/tcp, 0.0.0.0:32773->8080/tcp# curl -I 127.0.0.1:32773HTTP/1.1 200
将Docker镜像导出以便于本地使用
# docker export d3219e60d2b2 > docker_tomcat.tar# gzip docker_tomcat.tar# docker start d3219e60d2b2# docker ps -aCONTAINER ID COMMAND PORTS d3219e60d2b2 "/usr/bin/supervisord" 0.0.0.0:32776->22/tcp, 0.0.0.0:32775->8080/tcp# docker cp docker_tomcat.tar.gz 63730c15f13e:/opt/apache-tomcat-8.5.0/webapps/ROOT/docker_tomcat.html# wget -b -c 公网ip:32775/docker_tomcat.html > docker_tomcat.tar.gz
此处分享:
服务器选购需谨慎。 上方下载共计耗时12小时。 选择更适合自己的方式很重要。
Web部署
源码展示 (非必须)
UnmodifiedSet.java
import java.util.Collection;import java.util.Iterator;import java.util.Set;/** * * 毕竟将Guava引入到pom里面去也是件比较麻烦的事情, 因此直接给定一个默认的实现 * * @author http://blog.csdn.net/qyp199312/ * @since 2016-05-09 */public class UnmodifiedSet<E> implements Set<E> { protected transient int size = 0; @Override public int size() { return size; } @Override public boolean isEmpty() { return size() == 0; } @Override public boolean contains(Object o) { return false; } @Override public Iterator<E> iterator() { throw new UnsupportedOperationException(); } @Override public Object[] toArray() { throw new UnsupportedOperationException(); } @Override public <T> T[] toArray(T[] a) { throw new UnsupportedOperationException(); } @Override public boolean add(E e) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @Override public boolean containsAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } @Override public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); }}
UnmodifiedSet.java
import java.util.Collection;import java.util.Iterator;import java.util.Map;import java.util.Set;/** * * 毕竟将Guava引入到pom里面去也是件比较麻烦的事情, 因此直接给定一个默认的实现 * * @see java.util.Collections.UnmodifiableMap * @author http://blog.csdn.net/qyp199312/ * @since 2016-05-09 */public class UnmodifiableMap<K, V> implements Map<K, V> { @Override public int size() { return entrySet().size(); } @Override public boolean isEmpty() { return size() == 0; } @Override public boolean containsKey(Object key) { throw new UnsupportedOperationException(); } @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } @Override public V get(Object key) { throw new UnsupportedOperationException(); } @Override public V put(K key, V value) { throw new UnsupportedOperationException(); } @Override public V remove(Object key) { throw new UnsupportedOperationException(); } @Override public void putAll(Map<? extends K, ? extends V> m) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public Set<K> keySet() { throw new UnsupportedOperationException(); } @Override public Collection<V> values() { throw new UnsupportedOperationException(); } @Override public Set<Entry<K, V>> entrySet() { throw new UnsupportedOperationException(); } @Override public String toString() { Iterator<Entry<K,V>> i = entrySet().iterator(); if (! i.hasNext()) return "{}"; StringBuilder sb = new StringBuilder(); sb.append('{'); for (;;) { Entry<K,V> e = i.next(); K key = e.getKey(); V value = e.getValue(); sb.append(key == this ? "(this Map)" : key); sb.append('='); sb.append(value == this ? "(this Map)" : value); if (! i.hasNext()) return sb.append('}').toString(); sb.append(',').append(' '); } }}
EnvironmentUtils.java
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Map.Entry;import java.util.Properties;import java.util.Set;import java.util.concurrent.ConcurrentHashMap;/** * * 可获取到 java "-D key=value" 的环境变量 * * @author http://blog.csdn.net/qyp199312/ * @since 2016-05-09 */public class EnvironmentUtils { private static final transient Map<String, String> enVir = System.getenv(); private static final transient Map<Object, Object> profile = System.getProperties(); private static final ConcurrentHashMap<String, String> properties = new ConcurrentHashMap<String, String>(); private static final Set<String> fileName = new HashSet<String>(); static { cp(enVir, properties); cp(profile, properties); } private static final <K, V> void cp(Map<K, V> source, Map<String, String> target) { for (Entry<K, V> entry : source.entrySet()) { target.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue())); } } public static Map<String, String> environment() { return new UnmodifiableMap<String, String>() { @Override public int size() { return properties.size(); } @Override public String get(Object k) { return properties.get(k); } @Override public boolean containsKey(Object k) { return properties.containsKey(k); } @Override public Set<String> keySet() { return new UnmodifiedSet<String>() { }; } }; } public static Map<String, String> load(String filePath) throws IOException { if (fileName.contains(filePath)) { return environment(); } InputStream is = EnvironmentUtils.class.getResourceAsStream(filePath); if (is == null) { is = EnvironmentUtils.class.getClassLoader().getResourceAsStream(filePath); } if (is == null) { File file = new File(filePath); if (file.exists()) { is = new FileInputStream(file); } } if (is != null) { Properties p = new Properties(); p.load(is); cp(p, properties); fileName.add(filePath); is.close(); } return environment(); } public static String get(String k) { return properties.get(k); } public static String getWithReplace(String k, String replace) { String v; return (v = properties.get(k)) == null ? replace : v; } public static String getIfNull(String k) { return getWithReplace(k, ""); } /** * 获取字段模糊匹配开头Value <p> * 不使用缓存, 在多线程环境下执行 #load 的时候可能会出现数据错误 * * @param k 模糊匹配的起始 * @return */ public static Map<String, String> getStart(final String k) { return new UnmodifiableMap<String, String>() { @Override public String get(Object key) { if (String.valueOf(key).startsWith(k)) { return properties.get(k); } return null; } @Override public Set<Entry<String, String>> entrySet() { return new UnmodifiedSet<Entry<String, String>>() { { Iterator it = iterator(); while (it.hasNext()) { super.size ++; } } public Iterator<Entry<String, String>> iterator() { return new Iterator<Entry<String, String>>() { private Iterator<Entry<String, String>> data = properties.entrySet().iterator(); private Entry<String, String> next = null; private int size = properties.size(); private int current = size; @Override public boolean hasNext() { return (next = nextData()) != null; } public Entry<String, String> nextData() { int size = this.size; while (data.hasNext()) { if (current != size) { size --; continue; } Entry<String, String> next = data.next(); if (next.getKey().startsWith(k)) { current --; return next; } } return null; } @Override public Entry<String, String> next() { return next; } public void remove() { throw new UnsupportedOperationException("remove"); } }; } }; } }; }}
GateController.java
import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;@Controllerpublic class GateController { @RequestMapping("key") @ResponseBody public String key(@RequestParam("key") String key) { return EnvironmentUtils.get(key); } @RequestMapping("start") @ResponseBody public String start(@RequestParam("key") String key) { return String.valueOf(EnvironmentUtils.getStart(key)); }}
开始访问
部署并启动服务
# docker run -it -d -p 22 -p 8080 tomcat /usr/bin/supervisord# docker ps -aIMAGE COMMAND PORTS tomcat "/usr/bin/supervisord" 0.0.0.0:32769->22/tcp, 0.0.0.0:32768->8080/tcp# docker cp web2-1.0-SNAPSHOT.war ccb21ae25ca7:/opt/apache-tomcat-8.5.0/webapps/
访问示例
# curl 127.0.0.1:32768/web2-1.0-SNAPSHOT/start?key=java.vm{java.vm.vendor=Oracle Corporation, java.vm.specification.version=1.8, java.vm.specification.vendor=Oracle Corporation, java.vm.name=Java HotSpot(TM) 64-Bit Server VM, java.vm.specification.name=Java Virtual Machine Specification, java.vm.info=mixed mode, java.vm.version=25.91-b14}# curl 127.0.0.1:32768/web2-1.0-SNAPSHOT/key?key=java.vm.infomixed mode
Get Port(Tomcat Only)
让Web获取Docker运行容器的端口
@RequestMapping("docker_port") @ResponseBody public String docker_port() throws MalformedObjectNameException, AttributeNotFoundException, MBeanException, ReflectionException, InstanceNotFoundException { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); Set<ObjectName> set = server.queryNames( new ObjectName("*:type=Connector,*"), Query.match( Query.attr("protocol"), Query.value("HTTP/1.1")) ); if (set != null) { for (ObjectName name : set) { Object scheme = server.getAttribute(name, "scheme"); String port = name.getKeyProperty("port"); if (scheme != null && "http".equalsIgnoreCase(scheme.toString())) { return port; } } } return String.valueOf(EnvironmentUtils.getStart("port")); }
测试结果:
# curl 127.0.0.1:49164/navigation-0.0.1-SNAPSHOT/docker_port 8080
让Web获取宿主机端口
web程序无法获取容器绑定端口。但是可以通过一定的方式得知:
- Tomcat遵循JMX规范,启动时将告知JMX启动端口以及Host,由此获取即可
- 将启动端口以及Host配置在环境变量里面,直接获取
脚本:
$ 在 bin/startup.sh倒数第二行加入:export JAVA_OPTS=" $JAVA_OPTS -Dhost_port=10086 -Dhost_mapping=domain.com"
测试结果:
# curl 127.0.0.1:49164/navigation-0.0.1-SNAPSHOT/key?key=host_mappingdomain.com# curl 127.0.0.1:49164/navigation-0.0.1-SNAPSHOT/key?key=host_port10086
通过发布时加入环境变量的方式可以轻松获取到宿主机Host以及映射给Docker Tomcat的端口。
0 0
- Docker学习二(部署一个可以自由获取环境变量的SpringWeb)
- Docker学习笔记(二)CentOS6.5部署Docker
- springweb mvc学习的相关网址
- 二阶魔方旋转 魔方可以对它的6个面自由旋转。 我们来操作一个2阶魔方(如图1所示):
- 自由输入法学习之二----自由输入法的安装
- 关于docker部署的一个简单应用(入门级别)
- [转] 一些可以自由获取的编程电子书
- 利用Flash制作一个可以自由拨动的时钟模具
- 利用Flash制作一个可以自由拨动的时钟模具
- 一个可以在浏览器上自由移动的div
- 安装部署一个docker的环境
- docker学习之二docker的安装
- Docker——安装部署(二)
- Docker学习(二)Docker架构
- Docker学习笔记之二:web开发和Tomcat部署
- 一个可以实现热部署的插件
- Docker 学习日志 (二)
- Docker学习笔记(二)
- xlistview的写法
- VS2010 ENTITY FRAMEWORK6 SQLite3 安装搭建环境
- Struts2简单构建
- SQL的四种连接-左外连接、右外连接、内连接、全连接
- Maven入门(含实例教程)
- Docker学习二(部署一个可以自由获取环境变量的SpringWeb)
- Git
- 将一个CIImage转换为我们的UIImage
- odroidXu4 GPIO
- linux文件权限
- git,切换以前的版本,增加代码,然后合并的操作步骤
- 基于POI的框架BingExcel的使用-轻松完成excel读写操作(1)
- hbase
- Android Studio使用Lint进行代码检查