天天看点

docker docker-compose volumes数据卷挂载问题

从4月份以来,我就来到公司这边实习了。使用golang基于gin-vue-admin框架二次开发,做一个数据库配置可视化的一个系统(公司的全部配置信息都存到一个专门的数据库里面了,由于配置信息的不一致性,数据库里面包含很多json字段的配置信息,每次修改的时候需要手动启动事务,手动书写sql修改,容易出现人工出错)。经过两个多月的实习,做了一个支持openid登录,修改配置操作信息记录,配置信息版本回退,支持动态增加字段。同时最近使用gin-vue-admin原有的autoCode代码生成进行修改,能够更快的生成贴合公司业务的代码,也就是方便基于gin-vue-admin框架的三次开发。

所以最近都在抽离业务,书写开发部署文档。公司的项目都是通过kubernetes部署了,但是本地开发的时候就有点麻烦了,导师叫我使用docker-compose一键部署开发环境,所以最近就踩了很多坑

1. Dockerfile不能执行shell脚本的问题

背景: gva 自带docker-compose指令编排,其中包含四个服务:web,server,mysql,redis。server启动以来mysql和redis,使用了一个

depends on

指令,让mysql和redis先于server启动。但是这里有一个很坑的地方,这里的

depends on

先行启动只是字面意思上的启动,server端不会等到mysql完全启动之后才启动。加上mysql有挂载初始化sql操作,所以会有各种因素让mysql启动的慢。而server端是先通过了代码编译直接运行二进制文件的,所以启动的会特别快。

下面是有关gin-vue-admin server端的后台代码镜像相关的Dockerfile 文件,有点docker基础的都能看得懂,无非就是两个阶段,第一个阶段是将文件复制进来进行打包,第二个阶段就是将第一阶段打包的二进制文件复制进第二个镜像里面去,以最小的方式进行镜像打包部署。

FROM golang:alpine

ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io,direct
WORKDIR /go/src/gin-vue-admin
COPY . .

RUN go env && go build -o server .

FROM alpine:latest
LABEL MAINTAINER="[email protected][email protected]"

WORKDIR /go/src/gin-vue-admin

COPY --from=0 /go/src/gin-vue-admin ./

EXPOSE 8888

ENTRYPOINT ./server -c config.docker.yaml
           

问题: 这样就会出现一个问题,server端先启动了,然后去连接mysql,但是这个时候mysql还没有起来,就会出现

mysql connect refuse

的情况出现,从而出现项目使用不了的尴尬情况

解决办法: 在github上找一个

wait-for-it.sh

(点击)脚本 ,这个脚本是用于测试TCP连接的,当我们测试mysql连接为可用的时候,才去启动后台服务,这样就万无一失了。但是我们可以看到原有的server Dockerfile文件,二阶段打包是基于

alpine

的,这个系统是linux最小的操作系统,只支持最小的功能,所以在执行

wait-for-it.sh

脚本的时候,会报错

no such file or directory

。将

FROM golang:alpine

改成

FROM golang:1.14.12

这种完整的只包含golang开发环境的镜像源即可

温馨提示:如果是在window操作系统下打开过linux脚本并编辑过的话,很可能会出现shell脚本无法执行的框,我们可以打开相关的脚本,输入命令

:set ff

查看类型,如果显示为

fileformat=dos

的话,说明就仅仅是文本文件,我们要改为linux 脚本。

具体操作:输入

:set ff=unix

,

:wq!

保存退出即可

2. Docker volumes数据卷挂载问题

docker-compose部署主要是用于两个用途:一是为了部署使用,另外一个很重要的用途是部署开发环境方便开发。但是通过docker容器都是相互隔离的,要做到数据持久化就要使用volumes数据卷

在使用volumes数据卷的时候我在想能不能直接把整个项目挂载出去,然后直接运行容器就好了。但是容器通过数据卷挂载之后,就会报错:

no such file or directory

。这个点让我很纳闷,为什么挂载数据卷之前一切都是正常的,但是挂载了数据卷之后会出现找不到文件呢?后来看到了这一篇帖子:Docker volume 挂载时文件或文件夹不存在

数据卷挂载是从宿主机到容器的,如果容器里的文件和宿主机的文件出现重复的话,那么容器里的文件会被替换掉。由于我本地是没有二进制文件的,被替换之后找不到就是合情合理了。但是我想要对容器里面的项目进行修改的时候同步到我们本地,那要这么办?

  • 方法一,打镜像的时候只安装一个golang的环境,在本地打包成二进制文件之后,整个项目通过数据卷挂载的方式放入容器里
  • 方法二,在做数据卷挂载的时候,只挂载要改变的目录,例如我会在容器里面修改

    api

    ,

    router

    ,

    service

    ,

    middleware

    这几个包,那么我们就将这几个文件夹通过数据卷挂载的方式挂载进来,即只在这几个地方做同步,而不是整个项目进行同步操作