前言

  使用 Docker 部署应用的方式有多种,如每个应用单独部署再连接容器,如 docker-compose...

  本博客是单独部署的每一个容器。

本篇博客的操作有:

  ① 在本地创建两个 SpringBoot 项目(8090 端口和 8091 端口);分别配置 Dockerfile

  ② 把 SpringBoot 项目传输到服务器;打包成 Docker 镜像

  ③ 拉取官方 Nginx 镜像;配置 Nginx 在宿主机上的配置文件

  ④ 创建网络

  ⑤ 运行 SpringBoot 容器

  ⑥ 运行 Nginx 容器

  ⑦ 访问输出 'Hello Docker !!!server.port:'

源码

  GitHub 地址:https://github.com/intomylife/Docker

  Docker Hub 地址:

    ① https://hub.docker.com/r/intomylife/docker-springboot8090

    ② https://hub.docker.com/r/intomylife/docker-springboot8091

本地创建 SpringBoot 项目

POM 文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 继承父 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>

    <!-- 三坐标 -->
    <groupId>com.zwc</groupId>
    <artifactId>docker-springboot8090</artifactId>
    <version>1.0</version>

    <!-- 工程名称和描述 -->
    <name>docker-springboot8090</name>
    <description>使用 Docker 部署 SpringBoot + Nginx 实现负载均衡</description>

    <!-- 打包方式 -->
    <packaging>jar</packaging>

    <!-- 在properties下声明相应的版本信息,然后在dependency下引用的时候用${spring-version}就可以引入该版本jar包了 -->
    <properties>
        <!-- jdk -->
        <java.version>1.8</java.version>

        <!-- docker 前缀名,通常用在上传镜像 -->
        <docker.image.prefix>intomylife</docker.image.prefix>
        <!-- docker 镜像名称 -->
        <docker.image.name>docker-springboot8090</docker.image.name>
    </properties>

    <!-- 加入依赖 -->
    <dependencies>
        <!-- springboot 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- springboot 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 插件依赖 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <!-- Docker 插件 -->
            <plugin>
                <!-- 三坐标 -->
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.1.1</version>
                <!-- 配置信息 -->
                <configuration>
                    <!-- 镜像名称 -->
                    <imageName>${docker.image.prefix}/${docker.image.name}:${project.version}</imageName>
                    <!-- Dockerfile 文件的位置 -->
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <!-- 文件资源 -->
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                    <!-- 打包后的名称 -->
                    <buildArgs>
                        <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • <docker.image.prefix> Docker 镜像前缀 :一般会被镜像名称节点引用在前面。为仓库的用户名
  • <docker.image.name> Docker 镜像名称:为此仓库的名称
  • <imageName> 镜像名称:仓库用户名/镜像名称:镜像版本号
  • 如果想接下来把打包好的镜像传输到仓库中,那么这里 <imageName> 镜像名称要按照格式来

application.properties

server.port=8090
  • 配置了端口

Dockerfile 文件

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
  • 注意此文件的路径为 :src/main/docker/
  • 此文件是构建 Docker 的核心文件
  • FROM openjdk:8-jdk-alpine:基础镜像环境 JDK1.8
  • VOLUME /tmp:指定了挂载目录
  • ARG JAR_FILE:和上面 POM 文件中配置的 buildArgs 对应,动态获取打包后的名称
  • ADD ${JAR_FILE} app.jar:把生成的 jar 包拷贝到 Docker 容器中并命名为 app.jar
  • 最后一行是修改 Tomcat 随机数生成方式,加快 Tomcat 启动

Controller 前端控制器

package com.zwc.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName HelloDockerController
 * @Desc TODO   say hello - 前端控制器
 * @Date 2019/5/3 17:18
 * @Version 1.0
 */
@RestController
public class HelloDockerController {

    @Value("${server.port}")
    private String port;

    /*
     * @ClassName HelloDockerController
     * @Desc TODO   say hello
     * @Date 2019/5/3 17:21
     * @Version 1.0
     */
    @RequestMapping("/")
    public String say(){
        return "Hello Docker !!!server.port:" + port ;
    }

}
  • 读取配置文件中的端口,并输出

  注:此次部署有两个 SpringBoot 项目,上面只是简单介绍了其中一个,还有另一个只是端口不一样,

         其他基本一致。有兴趣可以下载源码查看。

 


 

服务器上部署环境

CentOS7中安装Maven3.6.0

CentOS7中安装Maven3.6.0

CentOS7中安装Docker

CentOS7中安装Docker

传输

  1. 打开下载好的 MobaXterm,使用 SSH 连接方式

  2. 连接成功后默认到 root 目录

  3. MobaXterm 左边是目录,在左边目录的最底部,有个选择框(Follow terminal folder)把它勾选上。

      勾选上它后,目录就会跟着你的命令动态发生变化

  4. 输入命令 cd /usr/local/ -> 进入目录

  5. 输入命令 mkdir JavaWork -> 新建文件夹

  6. 输入命令 cd JavaWork -> 进入目录

  7. 把本地的 SpringBoot 项目文件夹拖拽到 MobaXterm 左边目录中

  8. 传输需要一点点时间,也可以在 MobaXterm 左边目录底部看到传输进度

SpringBoot 项目打包 Docker 镜像

  1. 输入命令 cd /usr/local/JavaWork/docker-springboot-nginx-> 进入目录

      注意: docker-springboot-nginx 是从本地传输到服务器上的 SpringBoot 项目

  2. 如果是直接使用我上传的项目源码,这时会有两个文件夹,是两个单独的项目

  3. 输入命令 cd docker-springboot8090/ -> 进入工程目录

  4. 输入命令 mvn clean -> 清除 target

  5. 输入命令 mvn install -> 打 jar 包

  6. 输入命令 mvn package docker:build -> 使用 Maven 打包 Docker 镜像

  7. 输入命令 cd ../docker-springboot8091/ -> 进入另一个工程目录

  8. 输入命令 mvn clean -> 清除 target

  9. 输入命令 mvn install -> 打 jar 包

 10. 输入命令 mvn package docker:build -> 使用 Maven 打包 Docker 镜像

 11. 第一次打包需要一点时间,最后看到 'BUILD SUCCESS' 等字样就证明打包成功了

拉取官方 Nginx 镜像

  1. 输入命令 systemctl  start docker.service -> 启动 Docker 服务

  2. 输入命令 docker pull nginx:1.8 -> 拉取 Nginx 镜像

配置 Nginx 在宿主机上的配置文件

  1. 输入命令 cd /usr/local/ -> 进入目录

  2. 输入命令 mkdir docker -> 创建文件夹

  3. 输入命令 cd docker/ -> 进入目录

  4. 轮流输入命令 mkdir nginx、cd nginx、mkdir conf -> 创建 nginx 目录以及 conf 目录

  5. 输入命令 cd /usr/local/docker/nginx/conf/ -> 进入目录

  6. 输入命令 touch nginx.conf -> 新建文件

  7. 输入命令 vim nginx.conf -> 编辑文件,粘贴下面内容

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    upstream dispense {
        server springboot-8090:8090 weight=1;
        server springboot-8091:8091 weight=2;
    }

    server {
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            proxy_pass   http://dispense;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}
  
  • 通过配置 upstream 节点分发请求,达到负载均衡的效果
  • 注意 springboot-8090 和 springboot-8091 都是等会启动的 SpringBoot 容器的名称
  • 使用 weight 设置权重
  • location 节点中配置代理 proxy_pass 为 http://dispense; 即为上面配置 upstream 的名称
  • 注意我把默认端口 80 更改为 8080 了,因为我的服务器上 80 端口有别的应用在使用

  8. 轮流输入命令 esc -> shift 冒号 -> wq -> 回车 

运行 Docker 镜像

创建网络

  1. 输入命令 docker network create --driver bridge nginx_bridge -> 创建网络

  2. 输入命令 docker network ls -> 查看网络

运行 SpringBoot 容器

  1. 输入命令 docker images -> 查看构建的镜像

  2. 输入命令

docker run -p 8090:8090 --name springboot-8090 --network nginx_bridge -d intomylife/docker-springboot8090:1.0

  • -p:端口映射(宿主机端口:容器端口)
  • --name:启动后的容器名称
  • --network:连接到网络
  • -d:后台启动
  • intomylife/docker-springboot8090:1.0:启动的镜像

  3. 输入命令

docker run -p 8091:8091 --name springboot-8091 --network nginx_bridge -d intomylife/docker-springboot8091:1.0

  • -p:端口映射(宿主机端口:容器端口)
  • --name:启动后的容器名称
  • --network:连接到网络
  • -d:后台启动
  • intomylife/docker-springboot8091:1.0:启动的镜像

运行 Nginx 容器

  1. 输入命令 docker images -> 查看构建的镜像

  2. 输入命令

docker run -p 8080:8080 --network nginx_bridge --env springboot-8090=springboot-8090 --env springboot-8091=springboot-8091 -v /usr/local/docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -d nginx:1.8

  • -p:端口映射(宿主机端口:容器端口)
  • --network:连接到网络
  • --env:配置 Nginx 镜像中 nginx.conf 配置文件中的 SpringBoot 容器名
  • springboot-8090:等号前面的为 nginx.conf 配置文件中的 SpringBoot 容器名
  • springboot-8090:等号后面的为上面启动的 SpringBoot 容器 --name 名称
  • springboot-8091:与 springboot-8090 一致
  • -v:映射配置文件(宿主机目录:容器目录)

  3. 使用 ip + 8080 访问,看到 'Hello Docker !!!server.port:'  + 端口,多刷新几次页面,会发现

      8091 端口和 8090 端口出现的频率是 2:1,

      如果是这样的话就证明整个部署过程就成功了(注意安全组和端口)

 


 

安全组

  注:如果服务器是在阿里云租用的需要设置安全组

  1. 登录到阿里云

  2. 进入到 '云服务器 ECS' 控制台

  3. 左侧栏中选择 '实例'

  4. 进入实例详情,点击左侧栏中 '本实例安全组'

  5. 点击安全组中的 '配置规则'

  6. 点击 '添加安全组规则' 按钮

  7. 配置 8080 、 8090 和 8091 端口

防火墙

  注:如果服务器是在阿里云租用的需要开启防火墙。服务器是默认不开启防火墙的,感觉不安全

  1. 输入命令 systemctl status firewalld -> 查看防火墙状态

  2. 输入命令 systemctl start firewalld -> 开启防火墙

  3. 如果你不想开防火墙的话,那就输入命令 systemctl stop firewalld -> 关闭防火墙

  4. 输入命令 systemctl restart firewalld.service -> 重启防火墙

端口

  注:端口操作需要在开启防火墙的情况下才能执行成功。如下两条命令只需要执行一组即可

  1. 输入命令 firewall-cmd --permanent --zone=public --add-port=8080/tcp -> 永久开放 8080 端口

      输入命令 firewall-cmd --permanent --zone=public --add-port=8090/tcp -> 永久开放 8090 端口

      输入命令 firewall-cmd --permanent --zone=public --add-port=8091/tcp -> 永久开放 8091 端口

  2. 输入命令 firewall-cmd --zone=public --add-port=8080/tcp -> 临时开放 8080 端口

      输入命令 firewall-cmd --zone=public --add-port=8090/tcp -> 临时开放 8090 端口

      输入命令 firewall-cmd --zone=public --add-port=8091/tcp -> 临时开放 8091 端口

 


 

把打包好的镜像传输到仓库中

  注:这里选择 Docker Hub 官方仓库

  1. 如果没有账号的话先注册一个,填写用户名邮箱及密码等信息提交,到邮箱中确认即可

  2. 确保 Docker 服务已经启动:systemctl  start docker.service -> 启动 Docker 服务

  3. 输入命令 docker login -> 登录 Docker Hub

  4. 出现 'Login Succeeded' 等字样就证明登录成功了

  5. 输入命令 docker push intomylife/docker-springboot8090:1.0 -> 把镜像传输到仓库中

      intomylife 为 Docker Hub 仓库用户名

      docker-springboot8090 为 镜像名称

      1.0 为镜像版本

  6. 在自己的仓库中就可以看到此镜像了,注意此时镜像为公开的

  7. 因为我此次打包的 SpringBoot 项目是样例,里面没有很隐私的信息,所以公开的也没关系

      如果你不想被别人下载你的镜像,你也可以设置为私有的(貌似有费用),当然也可以搭建私库

把仓库中的公有镜像拉取到服务器中

  1. 输入命令 docker pull intomylife/docker-springboot8090:1.0 -> 把镜像拉取到服务器中

      intomylife 为 Docker Hub 仓库用户名

      docker-springboot8090 为 镜像名称

      1.0 为镜像版本

 


 

扩展

CentOS7中常用命令行

 

希望能够帮助到你

over

 

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐