├── .gitignore ├── LICENSE ├── README.md ├── code ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── bingo │ │ └── helloworld │ │ └── HelloWorld.java │ └── webapp │ ├── META-INF │ └── MANIFEST.MF │ └── WEB-INF │ └── web.xml ├── config └── mysql │ └── custom.cnf ├── docker-compose.yml ├── java-maven-tomcat ├── Dockerfile ├── build.sh ├── settings.xml └── sources.list └── mysql └── Dockerfile /.gitignore: -------------------------------------------------------------------------------- 1 | data/ 2 | log/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jaquan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker: Ubuntu, Tomcat, Maven and JAVA Stack 2 | ## 背景 3 | Hi,JAVA! 4 | 5 | JAVA 的项目通常都比较繁琐,为了标准化流程与简易化部署,本项目根据官方示例构建一套简易的 JAVA 的开发/运行环境(Ubuntu, Tomcat, Maven and JAVA Stack),最终达到 build,ship,run! 6 | 7 | ## 依赖 8 | 9 | * [Git](https://git-scm.com/downloads) 10 | * [Docker](https://www.docker.com/products/docker/) `>= 1.12` 11 | * [Docker-Compose](https://www.docker.com/products/docker/) `Windows/macOS 版 Docker 已包含` 12 | 13 | > 由于众所周知的原因,梯子不够坚固的童鞋请使用 [国内镜像](http://get.daocloud.io/) 以及 [加速器](https://www.daocloud.io/mirror.html#accelerator-doc)。 14 | 15 | ## 快速体验 16 | 1. `$ git clone https://github.com/springjk/java-in-docker` 17 | 2. `$ cd java-in-docker` 18 | 3. `$ docker-compose up` 19 | 4. 访问 [http://127.0.0.1](http://127.0.0.1) 20 | 21 | 22 | 23 | ![java-in-docker](http://oac57xnsh.bkt.clouddn.com/java-in-docker.jpg) 24 | 25 | 运维命令: 26 | 27 | ```bash 28 | $ docker-compose help # docker-compose 命令帮助 29 | $ docker-compose up # 创建并启动 docker 编排服务 30 | $ docker-compose down # 停止并移除 docker 编排服务 (更改配置文件时建议使用) 31 | $ docker-compose exec java-maven-tomcat bash # ssh 登入 java 容器 32 | ``` 33 | 34 | 35 | ## 加载项目 36 | 上述方式为体验项目使用,运行的为 `code` 目录下的示例代码,实际使用中我们需要加载自己项目的代码,这里有两种方式:挂载项目目录和导入到项目中,选择一种你喜欢的即可。 37 | 38 | ### 挂载项目目录 39 | 1. 修改 `docker-compose.yml` 中的代码挂载目录为你源代码目录(pom.xml 的父级目录) 40 | 2. `$ docker-compose up` 41 | 42 | ### 导入到项目中 43 | 1. `$ cd {your-project-path}` 44 | 2. `$ git submodule add https://github.com/springjk/java-in-docker` 45 | 2. `$ cd java-in-docker` 46 | 3. `$ docker-compose up` 47 | 48 | ## 数据库信息 49 | * **DB_HOST** : `mysql` 50 | * **DB_PORT** : `3306` 51 | * **DB_NAME** : `docker` 52 | * **DB_USER_NAME** : `root` 53 | * **DB_USER_PWD** : `docker` 54 | 55 | 此处的数据库连接地址 `DB_HOST` 值为 `mysql` 是因为名为 `java-maven-tomcat` 的容器 `link` 了名为 `mysql` 的容器,故 `java-maven-tomcat` 容器中会在自己的 `/etc/hosts` 中添加一条 `1xx.xx.xx.xx mysql` 的 host,这会将 `http://mysql` 这个地址指向 `mysql` 容器的实际内网地址,等效于常见的 `http://localhost` 。 56 | 57 | ## 数据持久化 58 | 容器内的数据会随着容器的销毁而丢失,所以需要配置 `docker-compose.yml` 文件将以下目录同步到你的物理机目录进行持久化: 59 | 60 | * `/root/.m2` Maven 的 jar 包缓存目录,挂载后将无需每次构建时重新下载。 61 | * `/var/lib/mysql` MySQL 的文件存放目录,必须挂载,否则销毁容器后数据丢失。 62 | * `/usr/local/tomcat/logs` Tomcat 的日志目录,挂载后查看日志无须进入容器内部。 63 | 64 | Windows 下挂载目录写法示例:`d:/project/`,macOS 与 Linux 下如挂载目录后出现无法写入则是权限问题,ssh 登陆容器后对文件夹给与写入权限即可。 65 | 66 | ## 项目部署 67 | 数据库信息,暴露端口等信息都在 `docker-compose.yml` 中配置,一切调试完成后可在启动命令后添加 `-d` 参数,让其后台启动,此时如果想实时查看启动日志可以使用 `docker-compose logs -f` 进行查看。 68 | 69 | ``` bash 70 | # 后台启动运行 71 | $ docker-compose up -d 72 | 73 | # 跟踪查看启动日志 74 | $ docker-compose logs -f 75 | ``` 76 | 77 | ## 版本信息 78 | * **JAVA** :`1.8` 79 | * **MySQL** :`5.7` 80 | * **Maven** :`3.3.9` 81 | * **Tomcat** :`8.5.3` 82 | 83 | 版本信息可在 `Dockerfile` 中进行修改,修改 `Dockerfile` 后需要将 `docker-compose` 中的构建方式改为构建本地镜像: 84 | 85 | ``` bash 86 | # 免构建镜像 87 | #image: registry.cn-hangzhou.aliyuncs.com/springjk/java-maven-tomcat 88 | # 构建本地镜像 89 | build: ./java-maven-tomcat 90 | ``` 91 | 92 | 修改完成后启动时需要重新构建镜像: 93 | 94 | ``` bash 95 | $ docker-compose up --build 96 | ``` 97 | 98 | ## 目录结构 99 | 100 | ``` 101 | ├── LICENSE 102 | ├── README.md 103 | ├── code # JAVA 演示代码 104 | │   ├── pom.xml 105 | │   └── src 106 | │   ├── main 107 | │   │   ├── java 108 | │   │   │   └── com 109 | │   │   │   └── bingo 110 | │   │   │   └── helloworld 111 | │   │   │   └── HelloWorld.java 112 | │   │   ├── resources 113 | │   │   └── webapp 114 | │   │   ├── META-INF 115 | │   │   │   └── MANIFEST.MF 116 | │   │   └── WEB-INF 117 | │   │   ├── lib 118 | │   │   └── web.xml 119 | │   └── test 120 | │   ├── java 121 | │   └── resources 122 | ├── data # 容器数据挂载目录 123 | │   ├── maven 124 | │   └── mysql 125 | ├── docker-compose.yml # docker-compose 配置文件 126 | ├── java-maven-tomcat 127 | │   ├── Dockerfile # JAVA-Tomcat-Maven 构建文件 128 | │   └── build.sh 129 | ├── log # 容器日志挂载目录 130 | │   └── tomcat 131 | └── mysql 132 | └── Dockerfile # MySQL 构建文件 133 | ``` 134 | 135 | ## 工作流程 136 | `Dockerfile -->(build)–> Image -->(run)–> Container` 137 | 138 | 1. 构建 MySQL 镜像 139 | 2. 构建 JAVA-Tomcat-Maven 镜像 140 | 3. 挂载 MySQL 数据目录并启动 MySQL 容器 141 | 4. 挂载 JAVA 代码目录并启动 JAVA-Tomcat-Maven 容器 142 | 5. 执行 Maven 的代码构建脚本 `build.sh` 生成 WAR 包并放入 Tomcat 工作目录 143 | 6. 启动 Tomcat 144 | 145 | 更多请参考 [Docker Docs](https://docs.docker.com/)。 146 | 147 | ## License 148 | MIT -------------------------------------------------------------------------------- /code/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | bingo 5 | com.bingo.ledger 6 | 0.0.1-SNAPSHOT 7 | war 8 | com.bingo.ledger 9 | http://maven.apache.org 10 | 11 | UTF-8 12 | 13 | 14 | 15 | mysql 16 | mysql-connector-java 17 | 8.0.28 18 | 19 | 20 | javax.servlet 21 | servlet-api 22 | provided 23 | 2.5 24 | 25 | 26 | 27 | 28 | 29 | maven-compiler-plugin 30 | 2.3.2 31 | 32 | 1.8 33 | 1.8 34 | 35 | 36 | 37 | maven-war-plugin 38 | 2.2 39 | 40 | 3.0 41 | ledger 42 | false 43 | 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-surefire-plugin 48 | 49 | true 50 | 51 | true 52 | 53 | 2.17 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /code/src/main/java/com/bingo/helloworld/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package com.bingo.helloworld; 2 | 3 | import java.io.IOException; 4 | import java.io.PrintWriter; 5 | 6 | import java.sql.Connection; 7 | import java.sql.DriverManager; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.sql.Statement; 11 | 12 | import javax.servlet.ServletException; 13 | import javax.servlet.http.HttpServlet; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | public class HelloWorld extends HttpServlet{ 18 | 19 | // 创建静态全局变量 20 | static Connection conn; 21 | 22 | /* 获取数据库连接的函数*/ 23 | public static Connection getConnection() throws Exception { 24 | Connection con = null; 25 | 26 | try { 27 | Class.forName("com.mysql.jdbc.Driver"); 28 | 29 | con = DriverManager.getConnection("jdbc:mysql://mysql/docker", "root", "docker"); 30 | 31 | } catch (Exception e) { 32 | throw e; 33 | } 34 | 35 | return con; 36 | } 37 | 38 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 39 | 40 | StringBuilder out = new StringBuilder(""); 41 | 42 | resp.setContentType("text/html; charset=UTF-8"); 43 | resp.setCharacterEncoding("UTF-8"); 44 | 45 | PrintWriter pw = resp.getWriter(); 46 | 47 | try { 48 | conn = getConnection(); 49 | pw.println("" 50 | + "" 51 | + "" 52 | + "Hello World" 53 | + "" 54 | + "" 55 | + "

Weclcome JAVA in Docker

" 56 | + "

数据库连接成功,连接代码:

" 57 | + "

DriverManager.getConnection(\"jdbc:mysql://mysql/docker\", \"root\", \"docker\")

" 58 | + ""); 59 | } catch (Exception e) { 60 | System.out.println(e); 61 | pw.println("数据库连接错误,是否更改了 docker-compose 默认的数据库配置?"); 62 | } 63 | 64 | pw.close(); 65 | } 66 | 67 | public static void main(String[] args) { 68 | 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /code/src/main/webapp/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /code/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | webAppRootKey 9 | helloworld.root 10 | 11 | 12 | 13 | Helloworld 14 | com.bingo.helloworld.HelloWorld 15 | 16 | 17 | 18 | Helloworld 19 | / 20 | 21 | 22 | -------------------------------------------------------------------------------- /config/mysql/custom.cnf: -------------------------------------------------------------------------------- 1 | [client] 2 | default-character-set=utf8 3 | 4 | [mysqld] 5 | character-set-server = utf8 6 | collation-server = utf8_general_ci 7 | max_connections = 3000 8 | default-time-zone=timezone 9 | default-time-zone = '+8:00' 10 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | java-maven-tomcat: 2 | # 免构建镜像,未修改构建文件下等同于构建本地镜像,如使用本地 build 需注释此行并关闭 build 注释。 3 | image: registry.cn-hangzhou.aliyuncs.com/springjk/java-maven-tomcat 4 | # 构建本地镜像 5 | # build: ./java-maven-tomcat 6 | links: 7 | - mysql 8 | # 将容器的8080端口绑定到宿主机的80端口 9 | ports: 10 | - "80:8080" 11 | # java-maven-tomcat 容器启动后的运行命令 12 | command: "bash /tmp/build.sh" 13 | volumes: 14 | # 挂载 Maven 的缓存目录 15 | - ./data/maven:/usr/share/maven/ref/repository 16 | # 挂载 Tomcat 的 log 目录 17 | - ./log/tomcat:/usr/local/tomcat/logs 18 | # 挂载 JAVA 源代码目录 19 | - ./code:/tmp/code 20 | restart: always 21 | mysql: 22 | build: ./mysql 23 | expose: 24 | - "3306" 25 | # 将容器的3306端口绑定到宿主机的3360端口 26 | ports: 27 | - "3360:3306" 28 | environment: 29 | MYSQL_DATABASE: docker 30 | MYSQL_ROOT_PASSWORD: docker 31 | volumes: 32 | # 挂载 Mysql 数据目录,持久化数据库。 33 | - ./data/mysql:/var/lib/mysql 34 | - ./config/mysql:/etc/mysql/conf.d 35 | restart: always 36 | -------------------------------------------------------------------------------- /java-maven-tomcat/Dockerfile: -------------------------------------------------------------------------------- 1 | # 安装maven 2 | FROM maven:3.6.1-jdk-8 3 | 4 | #设置时区 5 | RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 6 | RUN echo "Asia/Shanghai" > /etc/timezone 7 | RUN dpkg-reconfigure -f noninteractive tzdata 8 | 9 | ENV CATALINA_HOME /usr/local/tomcat 10 | ENV PATH $CATALINA_HOME/bin:$PATH 11 | RUN mkdir -p "$CATALINA_HOME" 12 | WORKDIR $CATALINA_HOME 13 | 14 | # 安装tomcat 15 | ENV TOMCAT_MAJOR 8 16 | ENV TOMCAT_VERSION 8.5.42 17 | ENV TOMCAT_TGZ_URL http://mirrors.aliyun.com/apache/tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz 18 | 19 | RUN set -x \ 20 | && curl -fSL "$TOMCAT_TGZ_URL" -o tomcat.tar.gz \ 21 | && tar -xvf tomcat.tar.gz --strip-components=1 \ 22 | && rm bin/*.bat \ 23 | && rm -rf webapps/* \ 24 | && rm tomcat.tar.gz* 25 | 26 | # china mirrors 27 | ADD sources.list /etc/apt/sources.list 28 | ADD settings.xml /usr/share/maven/ref/ 29 | 30 | # 拷贝部署脚本到镜像 31 | ADD build.sh /tmp/ 32 | 33 | # 允许挂载 Tomcat 日志目录 34 | VOLUME /usr/local/tomcat/logs 35 | 36 | # 允许挂载源码目录 37 | VOLUME /tmp/code 38 | 39 | EXPOSE 8080 -------------------------------------------------------------------------------- /java-maven-tomcat/build.sh: -------------------------------------------------------------------------------- 1 | # 将源码拷贝至编译目录 2 | cp -r /tmp/code /tmp/build 3 | 4 | # 下载依赖 5 | cd /tmp/build && mvn dependency:resolve 6 | 7 | # 构建应用 8 | cd /tmp/build && mvn clean package -Dmaven.test.skip=true 9 | 10 | # 拷贝编译结果到指定目录 11 | rm -rf $CATALINA_HOME/webapps/* 12 | mv target/*.war $CATALINA_HOME/webapps/ROOT.war 13 | 14 | # 清理编译痕迹 15 | cd / && rm -rf /tmp/build 16 | 17 | # 启动tomcat 18 | bash $CATALINA_HOME/bin/catalina.sh run -------------------------------------------------------------------------------- /java-maven-tomcat/settings.xml: -------------------------------------------------------------------------------- 1 | 5 | /usr/share/maven/ref/repository 6 | 7 | 8 | 9 | alimaven 10 | central 11 | aliyun maven 12 | http://maven.aliyun.com/nexus/content/groups/public/ 13 | 14 | 15 | 16 | repo1 17 | central 18 | Human Readable Name for this Mirror. 19 | http://repo1.maven.org/maven2/ 20 | 21 | 22 | 23 | repo2 24 | central 25 | Human Readable Name for this Mirror. 26 | http://repo2.maven.org/maven2/ 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /java-maven-tomcat/sources.list: -------------------------------------------------------------------------------- 1 | deb http://mirrors.aliyun.com/debian/ jessie main 2 | deb http://mirrors.aliyun.com/debian/ jessie-updates main 3 | deb http://mirrors.aliyun.com/debian-security/ jessie/updates main 4 | -------------------------------------------------------------------------------- /mysql/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mysql:5.7.16 2 | 3 | EXPOSE 3306 --------------------------------------------------------------------------------