docker 部署JavaWeb、Mysql、Redis教程


本文将详细介绍如何在Linux下部署Javaweb、MySQL、redis三个容器并实现容器间通信。我将使用Dockerfile制作镜像,使用脚本分别启动这三个镜像的方式进行部署。本文分为以下几个模块:

  • docker基础入门
  • dockerfile编写以及镜像制作
  • 容器启动流程
  • 本地镜像发布到镜像仓库及镜像导出导入
  • docker-compose容器启动管理(了解)

docker基础入门

docker镜像与容器

​ docker里有镜像和容器两个重要的概念。此博客对镜像和容器之间的区别有介绍http://blog.csdn.net/chszs 。下面是我个人的理解:

​ 镜像类似操作系统的ISO光盘,而容器类似我们的操作系统。我们通过一张光盘可以安装多个操作系统,操作系统可以被用户使用并且修改关闭重启。而光盘一旦被制作完成之后,就无法修改了。

​ 也可以用Java的类和对象来做比喻。镜像相当于Java的class,而容器则是对象,所有的对象创建时都要依赖于class,一个class可以创建无数个对象,每个创建的对象在堆(heap)都有自己独立的内存空间。而容器也是如此,每个容器启动后都在宿主机上占用单独的空间,容器之间文件系统彼此隔绝,可以通过网络进行相互通信。

docker容器间相互通信

​ 可以参照这几篇篇博客,讲的非常全面

https://blog.csdn.net/smooth00/article/details/82842234

https://blog.csdn.net/u013355826/article/details/84987233

我们生产环境最终采用的是–net=host 模式,即与主机共用网络,这样使用的好处是容器直接相当于宿主机里的一个进程,容器间网络通信与普通的进程间通信方式相同,直接使用 localhost:port即可通信。而且我公司计划在一台服务器部署多个容器,使用多个域名共同映射到该服务器,然后在服务器使用nginx对不同域名的请求代理到不同的容器,达到一台云服务器部署多家客户应用的目的。这种情况下如果使用bridge的网络模式,则nginx的配置较为麻烦,故镜像共用宿主机的网络(–net=host)会较为方便。

​ 当然,使用 --link 做容器链接的代码示例也会提供,并且该代码实测可用

dockerfile编写以及镜像制作

Dockerfile编写

1.示例

先以一段正式的Dockerfile文件为例,文件名: Dockerfile

在这里插入图片描述

第1行 from tomcat:9.0

​ 即本镜像要引用tomcat9.0这个镜像,如果这个镜像在本地镜像存在则直接使用本地镜像,如果不存在则从远程镜像仓库获取,并安装到本地镜像。

第3行 MAINTAINER hejing "hejing@szlabsun.com"

​ 这行对docker镜像编译无实际影响,只是记录该镜像制作人和联系方式

第5行 WORKDIR /usr/local/tomcat/webapps/

​ workdir代表容器当前进入到此目录下 即相当于容器执行了 cd /usr/local/tomcat/webapps/命令

第7行 RUN rm -rf /usr/local/tomcat/webapps/*

​ run 命令 即相当于在容器执行shell命令 run 后面的即是shell命令

第9行 ADD springboot.war /usr/local/tomcat/webapps/ROOT.war

​ ADD 和COPY命令都是将本地的文件拷贝到容器内 ADD 宿主机文件或文件夹 容器内文件或文件夹

​ 该命令也可以用 ADD ./ /usr/local/tomcat/webapps/ 这条命令代表将当前目录下的所有文件拷贝到容器webapps/下,文件名称不会改变

第11行 RUN echo "Asia/Shanghai" > /etc/timezone

​ 让容器内的时间和宿主机时间一致

以上是制作tomcat带有我们自己的war包的镜像,以下再贴一份运行jar包的dockerfile

FROM anapsix/alpine-java:8_server-jre_unlimited

MAINTAINER hejing@szlabsun.com

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

RUN mkdir -p /opt/projects/weims

WORKDIR /opt/projects/weims

COPY ./weims.jar /opt/projects/weims

EXPOSE 7700

CMD java -jar -Xms512m -Xmx512m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC /opt/projects/weims/weims.jar
2.mysql数据库Dockerfile
FROM mysql:5.7

MAINTAINER hejing@szlabsun.com

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

COPY ./weims_sd.sql /docker-entrypoint-initdb.d

COPY ./weims_sd.sql /docker-entrypoint-initdb.d

该命令是将 ./下的sql文件放到docker容器数据库启动的初始脚本文件夹中,这样mysql在启动时会执行该脚本,建库建表。

3.redis 镜像dockerfile

redis无需做特别配置 直接运行 docker pull redis 即安装好redis镜像

4.javaweb项目(war包)
FROM tomcat:9.0

MAINTAINER hejing "hejing@szlabsun.com"

WORKDIR /usr/local/tomcat/webapps/

RUN rm -rf /usr/local/tomcat/webapps/*

ADD springboot.war /usr/local/tomcat/webapps/ROOT.war

RUN echo "Asia/Shanghai" > /etc/timezone

镜像制作

1.示例

​ 镜像制作要依赖于编写好的Dockerfile,宿主机进入dockerfile所在的目录,执行 docker build -t weims-hj212 /opt/dockerBuild/hj212/

docker build -t [images名称] [dockerfile所在目录]

以下是镜像build成功之后的显示效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-COdpibj1-1600758716019)(C:\Users\liucu\AppData\Roaming\Typora\typora-user-images\image-20200922112832296.png)]

镜像制作成功之后 执行 docker images 即可看到编译好的镜像

2.mysql镜像制作

首先 将dockerfile文件放到某一目录下,本示例为 opt/docker/mysql/

然后将初始化脚本也放到该目录下

执行 docker build -t weims-mysql /opt/docker/mysql 即可

3.redis镜像制作

即执行完 docker pull redis 即完成了redis镜像制作

docker容器启动流程

1.示例

以上步骤我们已经制作好了一个镜像,接下来我们要用此镜像来实例化一个容器,执行 docker run -d --name weims-hj212 --net=host weims-hj212

docker run 为运行docker容器的指令

-d 代表在后台运行

–name [containerName] 指定容器的名称

–net=host 指定网络模式为使用宿主机的网络

weims-hj212 此代表镜像的名称 该字段可以写镜像的名称也可以写镜像id

该指令各部分的位置不固定,可以自由组合 如 docker run weims-hj212 --name weims-hj212 --net=host -d

​ 这样一个容器就启动完成了 ,可以执行 docker ps 查看本机的容器运行状态

要进入我们刚刚启动的容器,则可以执行 docker exec -it weims-hj212 /bin/bash

这样 我们就进入了容器内部,可以查看容器的日志以及文件信息等

2.mysql容器启动

在任意目录下执行 docker run -d -p 3307:3306 -v /home/hejing/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf -v /opt/docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name weims-mysql weims-mysql --lower_case_table_names=1 可以成功启动mysql -p 3307:3306 将本机的3307端口与容器的3306端口做映射,即相当于nginx的反向代理功能,访问宿主机的3307端口即自动代理到容器的3306端口

3.redis容器启动

将reids的配置文件放到某一目录下,本示例的redis配置文件为 /root/redis/redis.conf 执行以下命令,redis即可成功运行

docker run -p 6379:6379 --name weims-redis -v /root/redis/redis.conf:/etc/redis/redis.conf  -v /root/redis/data:/data -d weims-redis redis-server /etc/redis/redis.conf --appendonly yes

启动命令解释如下:

-p 6379:6379:把容器内的6379端口映射到宿主机6379端口
-v /root/redis/redis.conf:/etc/redis/redis.conf:把宿主机配置好的redis.conf挂载到容器内的这个位置中
-v /root/redis/data:/data:把redis持久化的数据在宿主机内显示,做数据备份
redis-server /etc/redis/redis.conf:这个是关键配置,让redis不是无配置启动,而是按照这个redis.conf的配置启动
–appendonly yes:redis启动后数据持久化

启动后如果出现一些警告,可参考https://www.cnblogs.com/xsjzhao/p/10882870.html进行解决

4,javaweb容器启动

1.共用宿主机网络方式

配置文件中jdbc 配置中mysql地址 写 localhost:3307或者127.0.0.1:3307 即把mysql容器当成本机的一个进程即可,然后执行

docker run -d --name weims-admin --net=host weims-admin

至此,javaweb启动成功, 访问8080端口即可进入web项目

注:因为我在编写Javaweb的dockerfile时 没有修改tomcat的配置 端口是8080 ,要修改的话可以将自己的配置文件server.xml ADD进容器的tomcat/conf/下

2.通过link建立连接

在javaweb项目的配置文件中以容器名的方式配置mysql和redis的连接host

配置文件如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-od1dULlo-1600758716023)(C:\Users\liucu\AppData\Roaming\Typora\typora-user-images\image-20200922144054033.png)]

然后执行命令启动javaweb

docker run -d --name weims-admin -p 8080:8080 --link weims-mysql:weims-mysql --link weims-redis:weims-redis weims-admin

–link命令解析

–link [alias] [contianerName] --link 别名 容器名 代表使用别名映射到容器名,做法原理是将 别名写进本容器的host文件里 对应的ip则是被链接的容器的ip

这样javaweb项目在访问 weims-mysql时 会将其视为一个域名 去本机host找到该域名对应的ip

docker本地镜像发布到镜像仓库及镜像导出导入

1.本地镜像发布到镜像仓库

2.镜像导出导入

涉及的命令有export、import、save、load

save
  • 命令
    docker save [options] images [images...]

    示例
    docker save -o nginx.tar nginx:latest

    docker save > nginx.tar nginx:latest
    其中-o和>表示输出到文件,nginx.tar为目标文件,nginx:latest是源镜像名(name:tag)

load
  • 命令
    docker load [options]
  • 示例
    docker load -i nginx.tar

    docker load < nginx.tar
    其中-i和<表示从文件输入。会成功导入镜像及相关元数据,包括tag信息
export
  • 命令
    docker export [options] container
  • 示例
    docker export -o nginx-test.tar nginx-test
    其中-o表示输出到文件,nginx-test.tar为目标文件,nginx-test是源容器名(name)
import
  • 命令
    docker import [options] file|URL|- [REPOSITORY[:TAG]]
  • 示例
    docker import nginx-test.tar nginx:imp

    cat nginx-test.tar | docker import - nginx:imp
区别
  • export命令导出的tar文件略小于save命令导出的
  • export命令是从容器(container)中导出tar文件,而save命令则是从镜像(images)中导出
  • 基于第二点,export导出的文件再import回去时,无法保留镜像所有历史(即每一层layer信息,不熟悉的可以去看Dockerfile),不能进行回滚操作;而save是依据镜像来的,所以导入时可以完整保留下每一层layer信息。如下图所示,nginx:latest是save导出load导入的,nginx:imp是export导出import导入的。
建议

可以依据具体使用场景来选择命令

  • 若是只想备份images,使用save、load即可
  • 若是在启动容器后,容器内容有变化,需要备份,则使用export、import

docker-compose容器启动管理

docker-compose 是作为多个容器之间管理调度的工具,本例的docker-compose配置文件如下

version: '2'
services:
  weims-mysql:
    build:
      context: ./
      dockerfile: ./db/Dockerfile
    environment:
      MYSQL_ROOT_PASSWORD: DbWeims@2020
    restart: always
    container_name: weims-mysql
    image: weims-mysql
    ports:
      - 3306:3306
    volumes:
      - ./weims-mysql:/var/lib/mysql
    command: --lower_case_table_names=1

  weims-redis:
    image: redis:5.0.4
    restart: always
    container_name: weims-redis
    ports:
      - 6379:6379

  weims-admin:
    build:
      context: ./
      dockerfile: ./weims/Dockerfile
    restart: always
    container_name: weims-admin
    image: weims-admin
    ports:
      - 8085:8085
    depends_on:
      - weims-redis
      - weims-mysql
    links:
      - "weims-redis"
      - "weims-mysql"

该文件可以成功编译并且启动,但是存在以下问题

  1. mysql的root密码没有成设置
  2. weims-admin的web项目使用了–link ,mysql容器启动后的ip是172.0.0.2 , 但是项目启动后访问数据库域名映射为172.0.0.4

在咨询干devops的前同事后,了解到docker-compose在落地使用并不多,所以暂未纠结此处,打算暂时先用脚本的方式分别启动各容器,空闲时间学习k8s,以后用k8s管理容器

Logo

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

更多推荐