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
原创粉丝点击