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. Linux 的目录结构

    原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/cbbf47b0-f ...

  2. SpringCloud-服务注册与实现-Eureka创建服务提供者(附源码下载)

    场景 SpringCloud-服务注册与实现-Eureka创建服务注册中心(附源码下载): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...

  3. React-Native踩坑记录二

    1.Image组件的borderRadius画圆有平台兼容性问题,在IOS下会失效 解决方法有几种 (1)在外面包裹一层View,对View组件使用borderRadius就可以了,这是我的做法 (2 ...

  4. 用 Keras 实现单词级的 one-hot 编码 & 使用散列技巧的单词级的 one-hot 编码

    from keras.preprocessing.text import Tokenizer samples = ['The cat sat on the mat.', 'The dog ate my ...

  5. easybcd误删Win10启动项,UEFI恢复引导

    参考文章https://blog.csdn.net/A_Sen_A/article/details/89545311 想给电脑安Ubuntu双系统,期间根据一些不靠谱的文章用了easybcd软件,Ub ...

  6. Python高级特性——生成器(generator)

    通过上节的学习,我们知道使用列表生成式,可以直接创建一个列表.但是,有些时候,受到内存的限制等实际情况,列表生成式无法满足.比如,一个长度为1000万的列表,普通内存根本就不够,又或者实际处理的过程中 ...

  7. php 将科学计算法得出的结果转换成原始数据 NumToStr

    由于php最大只支持显示 15位因的数据运算,大于15位的2数加减乘除的数据的结果,会直接用科学计数法显示, 但在现实生活中,科学计数法不利于普通人识别,所以,本函数将:科学计数法的出的结果转换成原始 ...

  8. SpringBoot集成swagger2.0

    最近项目里要用到SpringBoot + swagger,查了其他小伙伴们的资料,或多或少有点问题,在此我再梳理一遍. 1.maven依赖 <parent> <groupId> ...

  9. 开启Hyper-V

    开启Hyper-V 添加方法非常简单,把以下内容保存为.cmd文件,然后以管理员身份打开这个文件.提示重启时保存好文件重启吧,重启完成就能使用功能完整的Hyper-V了. pushd "%~ ...

  10. 如何在linux上有2个python的情况下安装gensim

    安装python的问题 https://blog.51cto.com/liqingbiao/2083869 安装gensim https://blog.csdn.net/zhujiyao/articl ...