0、前言

相信点进来看这篇文章的同学们已经对 Docker Dompose 有一定的了解了,下面,我们拿最简单的例子来介绍如何使用 Docker Compose 来管理项目。

本文例子:

一个应用服务( Spring Boot 的 jar 包)、 Mysql 服务和 Redis 服务。在每次启动,我们要先将 Mysql 容器和 Redis 容器启动起来,再将应用容器运行起来,这其中还不要忘了在创建应用容器时将容器网络连接到 MySQL 容器和 Redis 容器上,以便应用连接上它们并进行数据交换。

1、项目结构

为了方便进行管理和迁移,我们建议将 Docker Compose 项目与搭建一个软件开发项目一样,将项目的内容聚集到一个文件目录中,下面是一个比较通用的项目结构:

└─ project
├─ app
├─ compose
│ └─ docker-compose.yml
├─ mysql
│ └─ my.cnf
├─ redis
└─ redis.conf

在这个目录结构中,区分了 5 个顶层目录:

  • app :用于存放程序工程,即代码、编译结果以及相关的库、工具等;
  • compose :用于定义 Docker Compose 项目;
  • mysql :与 MySQL 相关配置等内容;
  • redis :与 Redis 相关配置等内容;

2、准备程序配置

为了更方便在开发过程中对 MySQL、Redis 程序本身管理,所以我们会将它们的核心配置放置到项目里,再通过挂载的方式映射到容器中。

这样一来,我们就可以直接在我们宿主操作系统里直接修改这些配置,无须再进入到容器中了。

基于此,我们在完成目录的设计之后,首要解决的问题就是准备好这些程序中会经常变动的配置,并把它们放置在程序对应的目录之中。

我们常用下列几种方式来获得程序的配置文件:

  • 借助配置文档直接编写
  • 下载程序源代码中的配置样例
  • 通过容器中的默认配置获得
1)借助配置文档直接编写一个 MySQL 的配置文件:

我们先找到 MySQL 文档中关于配置文件的参考,也就是下面这个地址:

https://dev.mysql.com/doc/refman/5.7/en/server-options.html

我们根据这些内容,选取跟我们程序运行有影响的几项需要修改的参数,编写成 MySQL 的配置文件。

# ./mysql/my.cnf

[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
nice = 0 [mysqld]
skip-host-cache
skip-name-resolve
explicit_defaults_for_timestamp bind-address = 0.0.0.0
port = 3306 user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
log-error = /var/log/mysql/error.log
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES lc-messages-dir = /usr/share/mysql symbolic-links = 0
2)下载Redis源代码中的配置样例:

在 Redis 源代码中,就包含了一份默认的配置文件,我们可以基于上面做修改:

github上面的链接:https://github.com/antirez/redis/blob/3.2/redis.conf

其中我修改了最主要的密码:

# ./redis/redis.conf
##...
################################## SECURITY ################################### # Require clients to issue AUTH <PASSWORD> before processing any other
# commands. This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
# 连接Redis需要的密码
requirepass Redis123
##...

3、上传应用jar包到app文件夹,并编写Dockerfile文件

这个是基于java:8镜像提交的webapp镜像,大家可参考上一篇文章:https://blog.csdn.net/Howinfun/article/details/102514099

4、编写Docker Compose项目的定义文件

docker-compose.yml 文件在compose文件夹下,下面是我自己根据需求编写的:

version: "3"

services:

  redis:
image: redis:3.2
container_name: app_redis
volumes:
- ../redis/redis.conf:/etc/redis/redis.conf:ro
- ../redis/data:/data
command:
- redis-server
- /etc/redis/redis.conf
ports:
- 6379:6379 mysql:
image: mysql:5.7
container_name: app_mysql
volumes:
- ../mysql/my.cnf:/etc/mysql/my.cnf:ro
- ../mysql/data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
ports:
- 3306:3306 webapp:
build: ../app
container_name: app_web
depends_on:
- mysql
- redis
ports:
- "8888:8888"

稍微讲解一下:

version:版本号,最新为3

services:Compose项目的服务配置

redis:

  • image:基于redis:3.2镜像
  • container_name:容器名
  • volumes:第一个是将项目中的写好的配置文件通过挂载的方式映射到容器中,而且ro指定了文件为只读;第二个是将Redis 容器中的 /data 目录通过挂载的方式绑定到了宿主机上的目录中
  • command:创建容器时执行的命令,这里是启动redis服务的命令
  • ports:对外开放的访问端口号

mysql

  • image:基于mysql:5.7镜像
  • container_name:容器名
  • volumes:第一个是将项目中的写好的配置文件通过挂载的方式映射到容器中,而且ro指定了文件为只读;第二个是将MySQL 容器中的 /var/lib/mysql 目录通过挂载的方式绑定到了宿主机上的目录中
  • environment:为 MySQL 设置了初始密码
  • ports:对外开放的访问端口号

webapp:

  • build:通过Dockerfile构建镜像,这里是指定Dockerfile文件的路径
  • container_name:容器名
  • depends_on:依赖于mysql和redis容器(在 Docker Compose 为我们启动项目的时候,会检查所有依赖,形成正确的启动顺序并按这个顺序来依次启动容器。)
  • ports:对外开放的访问端口号

在这个项目里,我将 Redis 和 MySQL 的数据存储目录,也就是 Redis 容器中的 /data 目录和 MySQL 容器中的 /var/lib/mysql 目录通过挂载的方式绑定到了宿主机上的目录中。 这么做的目的是为了让 Redis 和 MySQL 的数据能够持久化存储,避免我们在创建和移除容器时造成数据的流失。

同时,这种将数据挂载出来的方法,可以直接方便我们打包数据并传送给其他开发者,方便开发过程中进行联调。

5、启动Compose项目

docker-compose up 命令类似于 Docker Engine 中的 docker run,它会根据 docker-compose.yml 中配置的内容,创建所有的容器、网络、数据卷等等内容,并将它们启动。与 docker run 一样,默认情况下 docker-compose up 会在“前台”运行,我们可以用 -d 选项使其“后台”运行。事实上,我们大多数情况都会加上 -d 选项。

docker-compose -p appweb -f ./compose/docker-compose.yml up -d

命令参数:

  • -p:项目名称
  • -f:指定docker-compose.yml文件路径
  • -d:后台启动
[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -p appweb -f ./compose/docker-compose.yml up -d
Building webapp
Step 1/5 : FROM java:8
---> d23bdf5b1b1b
Step 2/5 : MAINTAINER Howinfun
---> Using cache
---> f72d0468f1ff
Step 3/5 : VOLUME /tmp
---> Using cache
---> 902b3df17b06
Step 4/5 : ADD app.jar /root/docker_test/app.jar
---> 511f44917a82
Step 5/5 : ENTRYPOINT ["nohup","java","-jar","/root/docker_test/app.jar",">","/root/docker_test/app.log","&"]
---> Running in 4825ec9daf24
Removing intermediate container 4825ec9daf24
---> 5e009b2fc6ae
Successfully built 5e009b2fc6ae
Successfully tagged appweb_webapp:latest
WARNING: Image for service webapp was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating app_mysql ... done
Creating app_redis ... done
Creating app_web ... done

查看创建的镜像:

[root@izwz90lvzs7171wgdhul8az project2]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
appweb_webapp latest 5e009b2fc6ae 45 seconds ago 686MB
mysql 5.7 383867b75fd2 4 weeks ago 373MB
redis 3.2 87856cc39862 12 months ago 76MB

查看正在启动的容器:

[root@izwz90lvzs7171wgdhul8az project2]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ccaa96d508d1 appweb_webapp "nohup java -jar /ro?? About a minute ago Up About a minute 0.0.0.0:8888->8888/tcp app_web
790629b5e7d0 mysql:5.7 "docker-entrypoint.s?? About a minute ago Up About a minute 0.0.0.0:3306->3306/tcp, 33060/tcp app_mysql
610d0b89c267 redis:3.2 "docker-entrypoint.s?? About a minute ago Up About a minute 0.0.0.0:6379->6379/tcp app_redis

6、访问接口

容器启动后,我们尝试使用postman或者其他http工具去访问部署在容器中的应用接口。

7、网络配置

我们都知道,使用 Docker 打包镜像,我们可以在任意的环境下部署和运行项目,Docker 的容器能够很轻松的运行在开发者本地的电脑,数据中心的物理机或虚拟机,云服务商提供的云服务器,甚至是混合环境中。

但是,这里的每一个环境的IP地址可是不一样,而且,应用服务链接的Mysql数据库,或者Redis缓存那必定是要和部署环境的IP地址一一对应的,那么难道我们还需要每次都去修改配置文件的IP吗?

答案是:不用的!

在 Docker Compose 里,我们可以为整个应用系统设置一个或多个网络。要使用网络,我们必须先声明网络。声明网络的配置同样独立于 services 存在,是位于根配置下的 networks 配置。

下面我们尝试在docker-compose.yml中添加网络配置。

version: "3"

services:

  redis:
image: redis:3.2
container_name: app_redis
volumes:
- ../redis/redis.conf:/etc/redis/redis.conf:ro
- ../redis/data:/data
command:
- redis-server
- /etc/redis/redis.conf
ports:
- 6379:6379
networks:
- appnet mysql:
image: mysql:5.7
container_name: app_mysql
volumes:
- ../mysql/my.cnf:/etc/mysql/my.cnf:ro
- ../mysql/data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
ports:
- 3306:3306
networks:
- appnet webapp:
build: ../app
container_name: app_web
depends_on:
- mysql
- redis
ports:
- "8888:8888"
networks:
- appnet networks:
appnet:
driver: bridge

可以看到,我们在docker-compose.yml文件的最下面添加了关于网络的配置。网络名为appnet,网络驱动为 Bridge

Bridge 网络是 Docker 容器的默认网络驱动,简而言之其就是通过网桥来实现网络通讯。

然后在每个服务的下面都配置上服务所在的网格,就是上面的 appnet 了。

接下来,修改 application.properties 中的IP,改为容器名或者服务名作为网络地址。

例如我的配置文件要将 MySql 和 Redis 的IP,改为各自服务的容器名:

#Mysql
spring.datasource.url=jdbc\:mysql\://app_mysql\:3306/test?useUnicode\=true&characterEncoding\=utf-8&allowMultiQueries=true&&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456 #Redis
spring.redis.host=app_redis
spring.redis.password=Redis123..
spring.redis.database=1

8、停止项目

docker-compose up 相反,docker-compose down 命令用于停止所有的容器,并将它们删除,同时消除网络等配置内容,也就是几乎将这个 Docker Compose 项目的所有影响从 Docker 中清除。

docker-compose -p appweb -f ./compose/docker-compose.yml down --rmi all

命令参数:

  • -p:项目名称(up的时候有的,down一定也要带上,不然找不到network)
  • -f:docker-compose.yml路径
  • down:停止容器,并删除容器
  • --rmi all:删除项目的所有镜像
[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -p appweb -f ./compose/docker-compose.yml down --rmi all
Stopping app_web ... done
Stopping app_mysql ... done
Stopping app_redis ... done
Removing app_web ... done
Removing app_mysql ... done
Removing app_redis ... done
Removing network appweb_default
Removing image redis:3.2
Removing image mysql:5.7
Removing image appweb_webapp

注意:如果在使用 up 命令时指定了项目名,而在 down 命令时没有指定项目名会报错:

[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -f ./compose/docker-compose.yml down
Removing network compose_default
WARNING: Network compose_default not found.

9、重新利用up命令启动项目

docker-compose -p appweb -f ./compose/docker-compose.yml up -d

命令参数:

  • -p:项目名称
  • -f:指定docker-compose.yml文件路径
  • -d:后台启动
[root@izwz90lvzs7171wgdhul8az project2]# docker-compose -p appweb -f ./compose/docker-compose.yml up -d
Creating network "appweb_appnet" with driver "bridge"
Pulling redis (redis:3.2)...
3.2: Pulling from library/redis
f17d81b4b692: Pull complete
b32474098757: Pull complete
8980cabe8bc2: Pull complete
58af19693e78: Pull complete
a977782cf22d: Pull complete
9c1e268980b7: Pull complete
Digest: sha256:7b0a40301bc1567205e6461c5bf94c38e1e1ad0169709e49132cafc47f6b51f3
Status: Downloaded newer image for redis:3.2
Pulling mysql (mysql:5.7)...
5.7: Pulling from library/mysql
8f91359f1fff: Pull complete
6bbb1c853362: Pull complete
e6e554c0af6f: Pull complete
f391c1a77330: Pull complete
414a8a88eabc: Pull complete
fee78658f4dd: Pull complete
9568f6bff01b: Pull complete
76041efb6f83: Pull complete
ea54dbd83183: Pull complete
566857d8f022: Pull complete
01c09495c6e7: Pull complete
Digest: sha256:f7985e36c668bb862a0e506f4ef9acdd1254cdf690469816f99633898895f7fa
Status: Downloaded newer image for mysql:5.7
Building webapp
Step 1/5 : FROM java:8
---> d23bdf5b1b1b
Step 2/5 : MAINTAINER Howinfun
---> Using cache
---> f72d0468f1ff
Step 3/5 : VOLUME /tmp
---> Using cache
---> 902b3df17b06
Step 4/5 : ADD app.jar /root/docker_test/app.jar
---> 674b9e9f9766
Step 5/5 : ENTRYPOINT ["nohup","java","-jar","/root/docker_test/app.jar",">","/root/docker_test/app.log","&"]
---> Running in 428e426ccede
Removing intermediate container 428e426ccede
---> f0f5e8bf51cb
Successfully built f0f5e8bf51cb
Successfully tagged appweb_webapp:latest
WARNING: Image for service webapp was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating app_mysql ... done
Creating app_redis ... done
Creating app_web ... done
[root@izwz90lvzs7171wgdhul8az project2]#

上面我们可以很清楚的看到,启动项目时第一件事情就是创建项目配置的网络 appnet 了。

最后我们再尝试测试一下接口,可以发现是没有问题的。那么就是说,现在这个项目打包到哪里都可以运行了,而不用理会不同环境下的不同网络。

10、结束

到这里,利用 Docker Compose 搭建 Spring Boot 运行环境已经全部完成。其实只要掌握了这个搭建方法,以后不管是搭建 Spring Cloud 微服务,甚至是其他语言,例如 Python、Go等,方法都是一样的,最主要的是服务的配置和之间的依赖,即编写 Docker Compose 的定义文件 docker-compose.yml。

利用 Docker Compose 搭建 SpringBoot 运行环境(超详细步骤和分析)的更多相关文章

  1. 第2天 | 12天搞定Python,运行环境(超详细步骤)

    倘若有人告诉你,他在学习Python编程,却没有安装运行环境,那你赶紧叫他滚,并离他远点,因为他在欺骗你的感情. 没有安装运行环境,程序根本无法跑起来,对错不能知根知底,试问是在学编程,还是在跟空气对 ...

  2. PyCharm使用之利用Docker镜像搭建Python开发环境

      在我们平时使用PyCharm的过程中,一般都是连接本地的Python环境进行开发,但是如果是离线的环境呢?这样就不好搭建Python开发环境,因为第三方模块的依赖复杂,不好通过离线安装包的方式安装 ...

  3. 苹果MAC中安装并搭建Android开发环境的详细步骤

    Android的开发平台搭建主要需要的工具有:Java虚拟机JDK.Eclipse.Eclipse插件ADT(Android Developer Tool)和Android开发包SDK,以下是具体的安 ...

  4. Linux下搭建hadoop开发环境-超详细

    先决条件:开发机器需要联网 已安装java 已安装Desktop组 1.上传安装软件到linux上: 2.安装maven,用于管理项目依赖包:以hadoop用户安装apache-maven-3.0.5 ...

  5. 利用Docker搭建本地https环境的完整步骤

    利用Docker搭建本地https环境的完整步骤 这篇文章主要给大家介绍了关于如何利用Docker搭建本地https环境的完整步骤,文中通过示例代码将实现的步骤介绍的非常详细,对大家的学习或者工作具有 ...

  6. 利用Docker Compose快速搭建本地测试环境

    前言 Compose是一个定义和运行多个Docker应用的工具,用一个YAML(dockder-compose.yml)文件就能配置我们的应用.然后用一个简单命令就能启动所有的服务.Compose编排 ...

  7. Centos7安装Docker 基于Dockerfile 搭建httpd运行环境

    Centos7安装Docker 基于Dockerfile 搭建httpd运行环境 docker docker搭建 docker build 本文档完成目标内容如下 使用Docker搭建http服务器一 ...

  8. 使用Docker搭建Tomcat运行环境

    1 准备宿主系统 准备一个 CentOS 7操作系统,具体要求如下: 必须是 64 位操作系统 建议内核在 3.8 以上 通过以下命令查看您的 CentOS 内核: # uname -r 2 安装Do ...

  9. Docker Compose 搭建 Redis Cluster 集群环境

    在前文<Docker 搭建 Redis Cluster 集群环境>中我已经教过大家如何搭建了,本文使用 Docker Compose 再带大家搭建一遍,其目的主要是为了让大家感受 Dock ...

随机推荐

  1. ASP.NET MVC项目中EntityFramework"代码优先方法"的使用步骤

    EF提供了三种方式来实现项目,分别是: (1)代码优先方法: (2)模型优先方法: (3)数据库优先方法: 本篇主要记录在Vs2010环境下使用代码优先的方式实现数据库和后端代码数据交互,语言为C#, ...

  2. Tomcat系列(二)- EndPoint源码解析

    在上一节中我们描述了Tomcat的整体架构, 我们知道了Tomcat分为两个大组件,一个连接器和一个容器. 而我们这次要讲的 EndPoint的组件就是属于连接器里面的. 它是一个通信的端点,就是负责 ...

  3. conda pip 安装 dgl 并运行demo 出现:Segmentation fault (core dumped) 错误

    安装dgl 并运行的时候,出现了如上错误,很是郁闷:使用 gdb python; run train.py 进行调试,发现是torch的问题:我猜测估计是torch 安装的版本过于新:于是重新安装 1 ...

  4. JVM调优之服务内存超过阈值报警

    今早收到一条短信,具体报警信息如下: [UMP JVM监控内存报警]应用名:发券worker(jdos_couponwkr);KEY[coupon.send.worker.jvm],主机名:[host ...

  5. Skulpt在线模拟运行Python工具

    1. Skulpt是一个完全依靠浏览器端模拟实现Python运行的工具 2. 不需要预处理.插件或服务器端支持,只需编写python并重新载入即可. 3. 由于代码完全是在浏览器中运行的,所以不必担心 ...

  6. 《C#并发编程经典实例》学习笔记—2.9 处理 async void 方法的异常

    问题 需要处理从 async void 方法传递出来的异常. 解决方案 书中建议尽量不写 async void 这样的方法,如果非写不可,建议在方法内部 try catch 所有的代码,即在方法内部处 ...

  7. 如何在一台电脑上同时使用Gitee(码云)和Github?

    前言 最近重装了一下系统,用上了 win10,之前电脑上的开发环境和配置都被清除了,由于工作原因我需要经常使用 Gitee(码云)和 Github ,之前配置好了一个,但是不知道怎么同时配置两个,所以 ...

  8. k8s ingress 转发服务,内容显示不全问题

    0x00 事件 部署了 ingress ,并声明了两个路由 /eureka 和 /tomcat,/eureka 转发到了 eureka server 的服务端口,/tomcat 转发到了 tomcat ...

  9. Docker 常用操作命令

    一. docker安装  方式1 本地安装: 1)下载docker安装文件: 2)执行安装命令  yum localinstall *: 3)安装完之后 重启 systemctl restart do ...

  10. sql server一些快捷方式和操作技巧

    1.注释(ctrl+k+c) 和 取消注释(ctrl+k+u) 2.行号显示,如图: