docker制作镜像实战(图片上传)

1,222 阅读3分钟

前言

上一篇已经说过如何制作镜像(juejin.cn/post/684490…),下面我们以一个基于koa的图片上传服务为例。

准备图片上传代码

const Koa = require('koa')
const fs = require('fs')
const app = new Koa()
const koaBody = require('koa-body') //解析上传文件的插件
// 这两个变量从环境变量中读取
const { MAX_SIZE, FILE_TYPE } = require('./config')

const Path = require('path')
const serve = require('koa-static')
app.use(serve(Path.join(__dirname, '/pic/')))

app.use(koaBody({
  multipart: true,
  formidable: {
    maxFileSize: MAX_SIZE * 1024 * 1024    // 设置上传文件大小最大限制,默认2M
  }
}))
// 响应处理
app.use(async ctx => {
  let { files, method, path } = ctx.request; // 获取上传文件
  if (method !== 'POST' || path !== '/upload') return ctx.throw(404, 'Not found')
  if (!files) return ctx.throw(400, '请传人图片')
  // 验证图片类型
  if (!FILE_TYPE.split(',').includes(files['image'].type)) return ctx.throw(400, '图片类型错误')
  // 创建可读流
  const reader = fs.createReadStream(files['image']['path'])
  let filePath = Path.join(__dirname, `./pic/${files['image']['name']}`)
  let remotefilePath = `/${files['image']['name']}`
  // 创建可写流
  const upStream = fs.createWriteStream(filePath);
  // 可读流通过管道写入可写流
  reader.pipe(upStream);
  return ctx.body = {
    url: remotefilePath,
    message: "文件上传成功",
    cc: 0
  }
})
app.listen(3000)

配置文件(config.js):

// 两个参数都从环境变量中读取
// 图片大小限制
const MAX_SIZE = process.env.MAX_SIZE || 2
// 图片类型限制
const FILE_TYPE = process.env.FILE_TYPE || 'image/jpeg,image/png'

module.exports = {
  MAX_SIZE,
  FILE_TYPE
}

项目地址:github.com/Vongolatt/i….

Dockfile

# koa图片上传
# Version 1.0

# 基础镜像
FROM node:current-alpine

# 维护者信息
LABEL name="vongola" 

#ENV 设置环境变量
ENV MAX_SIZE=4 FILE_TYPE='image/jpeg,image/png'

#WORKDIR 相当于cd,当指定后,下面的run命令会在当前文件路径下执行
WORKDIR /home

#RUN 执行以下命令 
RUN wget https://github.com/Vongolatt/image-upload/archive/master.zip
RUN unzip master.zip \
&& cd image-upload-master/ \
&& mkdir pic \
&& npm install --production
ENTRYPOINT [ "node", "/home/image-upload-master/app.js" ]
#EXPOSE 暴露端口
EXPOSE 3000

这里我们基于node的alpine版本,这个版本的node会比其他版本小非常多,但是功能受限,可能会有bug,使用的时候需要注意。
然后设置图片大小和图片类型的默认值,拉取项目(这里用的wget命令,就不需要安装git了,是个取巧的办法),最后在入口处启动命令,并暴露3000端口。

构建Dockerfile

在Dockerfile所在目录执行以下命令(注意最后的小点):

docker build --no-cache -t image_upload:v1 .

QQ20191017-110120@2x.png

查看镜像:
QQ20191017-110359@2x.png

启动容器

docker run -itd -p 3000:3000 --rm --name upload -v /Users/vongola/Documents/Image/:/home/image-upload-master/pic  image_upload:v1

这里容器启动并且映射了图片保存路径,请把红色部分替换成你的路径,并且没有传递环境变量,所以默认为构建镜像时的环境变量。

测试容器

QQ20191017-110807@2x.png

QQ20191017-110939@2x.png

QQ20191017-111120@2x.png

这里可以看到png、jpeg图片都上传成功,并显示正常。

传递环境变量

前面我们没有传递环境变量启动了容器,现在测试一下环境变量的传递。首先关闭容器(由于启动容器时使用了--rm参数,所以关闭容器后会直接删除容器):

docker stop upload

传递环境变量

docker run -itd -p 3000:3000 --rm --name upload -e FILE_TYPE=image/jpeg -v /Users/vongola/Documents/Image/:/home/image-upload-master/pic  image_upload:v1

这里我们让FILE_TYPE=image/jpeg,测试图片上传,可以jpeg正常,png报错:

QQ20191017-113325@2x.png

总结

到这里就完成了一个非常简单的应用docker封装,但是还有很多问题没有考虑到。比如说:

  1. 代码层面,没有考虑图片上传重名的问题。
  2. 在拉取git项目时,也没有使用git命令,这对于一般的项目足够了,但是对于私有项目,还需要考虑git的配置。