[{"data":1,"prerenderedAt":701},["ShallowReactive",2],{"navigation":3,"post-\u002Fposts\u002F2018\u002Ffrontend-components-and-docker-deploy":20,"surroundPosts-\u002Fposts\u002F2018\u002Ffrontend-components-and-docker-deploy":688},[4,8,12,16],{"title":5,"path":6,"stem":7},"首页","\u002F","00.index",{"title":9,"path":10,"stem":11},"文章","\u002Fposts","01.posts",{"title":13,"path":14,"stem":15},"动态","\u002Fmoments","02.moments",{"title":17,"path":18,"stem":19},"关于","\u002Fabout","09.about",{"id":21,"title":22,"body":23,"class":666,"cover":666,"coverSize":666,"date":667,"description":29,"draft":668,"extension":669,"hideComments":668,"location":666,"meta":670,"navigation":414,"path":671,"readingTime":672,"seo":677,"sitemap":678,"stem":679,"tags":680,"time":685,"weather":686,"__hash__":687},"posts\u002Fposts\u002F2018\u002F20180414.frontend-components-and-docker-deploy.md","前端跨项目组件化及基于 Docker 的快速部署方案",{"type":24,"value":25,"toc":662},"minimark",[26,30,34,37,62,65,140,165,184,194,242,249,255,302,309,318,321,365,431,449,453,456,459,581,591,601,648,655,658],[27,28,29],"p",{},"最近静下心来写了几个项目，花了些时间重新整理了整套组件化方案和部署方案，记录一下。",[31,32,33],"h3",{"id":33},"跨项目组件化",[27,35,36],{},"前端的组件化不用多说了，发展到现在，无论是 React 的还是 Vue，都提供了相当方便的组件化实现。在日常项目中，有些组件其实是可以跨多个项目使用的，将这些组件抽离出来作为单独项目，并复用到其他项目中去，一来可以避免重复造轮子，加快开发速度，二来维护效率也高，一些 bugfix 或者新特性直接在组件中更新，项目中只需要更新引用版本号即可，方便快捷。",[27,38,39,40,44,45,48,49,51,52,54,55,58,59,61],{},"跨项目的组件化方式也很多，开发阶段可以用 ",[41,42,43],"code",{},"npm link","，相当于在主项目的 ",[41,46,47],{},"node_modules"," 目录中创建了一个链向组件项目的软链，方便是挺方便，但是有几个问题。一是 Eslint 的目录递归检查是基于最终实际目录的，也就是说虽然 Eslint 默认排除 ",[41,50,47],{}," 目录，但它依然会对该目录中的软链项目进行检查，一旦组件项目的 Eslint 规则和主项目的 Eslint 不一致的话，主项目 Eslint 就没法通过，这个比较蛋疼，就得临时禁用 Eslint 或者修改组件项目的规则。作为组件项目应该保证少依赖，而且要服务多个项目，没办法保证匹配各个项目的 Eslint 规则。第二个问题是，通过 ",[41,53,43],{}," 实现的依赖，不会体现在 ",[41,56,57],{},"package.json"," 中，如果通过 Docker 去部署，在 Docker 上是不知道你这个软链的，即便能够把软链写进去，在 Docker 中构建的时候，由于目录问题，也不能保证可以把组件项目文件拷过去。因此，在生产中，",[41,60,43],{}," 这个方案是没办法用的。",[27,63,64],{},"之前在国资的时候，采用的是通过组件项目的 git 地址来定位包，使用起来也很方便。如下：",[66,67,72],"pre",{"className":68,"code":69,"language":70,"meta":71,"style":71},"language-json shiki shiki-themes material-theme-lighter github-light github-dark","{\n  \"dependencies\": {\n    \"example-component\": \"git+ssh:\u002F\u002Fgit@xxx.com\u002Fexample-component.git#v1.0.0\"\n  }\n}\n","json","",[41,73,74,83,103,128,134],{"__ignoreMap":71},[75,76,79],"span",{"class":77,"line":78},"line",1,[75,80,82],{"class":81},"sP7_E","{\n",[75,84,86,90,94,97,100],{"class":77,"line":85},2,[75,87,89],{"class":88},"s39Yj","  \"",[75,91,93],{"class":92},"sseR_","dependencies",[75,95,96],{"class":88},"\"",[75,98,99],{"class":81},":",[75,101,102],{"class":81}," {\n",[75,104,106,109,113,115,117,121,125],{"class":77,"line":105},3,[75,107,108],{"class":88},"    \"",[75,110,112],{"class":111},"sZMiF","example-component",[75,114,96],{"class":88},[75,116,99],{"class":81},[75,118,120],{"class":119},"sjJ54"," \"",[75,122,124],{"class":123},"s_sjI","git+ssh:\u002F\u002Fgit@xxx.com\u002Fexample-component.git#v1.0.0",[75,126,127],{"class":119},"\"\n",[75,129,131],{"class":77,"line":130},4,[75,132,133],{"class":81},"  }\n",[75,135,137],{"class":77,"line":136},5,[75,138,139],{"class":81},"}\n",[27,141,142,143,146,147,150,151,153,154,157,158,160,161,164],{},"npm 支持通过 tag 来定位版本，组件项目发布的时候打一个 tag，对应的在项目中更新最后的版本号重新安装就可以完成升级了。由于之前没有用 Docker 部署，所以也没发现有什么问题。用了 Docker 的话，就会有些小问题。一般为了精简，都会采用基于 ",[41,144,145],{},"Alpine"," 的基础镜像，我目前的前端项目都是基于 ",[41,148,149],{},"node:8-alpine"," 来构建的。要知道，",[41,152,145],{}," 镜像本身只有 4.8M，",[41,155,156],{},"node:8-apline"," 也只有 20 几兆，非常精简。但是通过上面的这种方式，需要依赖 git，而 ",[41,159,145],{}," 显然是没有安装 ",[41,162,163],{},"git"," 的，也没有必要为了部署专门去安装一个 git。",[27,166,167,168,171,172,175,176,179,180,183],{},"于是便有了第三种方案，基于 Nexus 的 npm repository 方案。把包发布到 npm 上不太现实，大部分公司项目还是希望私有，和 maven 一样，Nexus 也支持 npm。创建一个 ",[41,169,170],{},"hosted"," 类型的 npm 仓库，例如 ",[41,173,174],{},"npm-hosted","，具体教程自行谷歌。但是我们又不希望给该仓库增加过多的压力，不想把所有 npm 或者 yarn 默认的 registry 改为 Nexus，没必要，因为即便改为 Nexus，在国内的网络环境，还是 proxy 到 ",[41,177,178],{},"https:\u002F\u002Fregistry.npm.taobao.org"," 上去了，而且会在 Nexus 上留下大量缓存，也经过了两层的下载，我尝试过，很蛋疼，在 Nexus 没有缓存第一次去下载的时候，还会有很多失败。后来发现 npm 也支持直接通过 ",[41,181,182],{},"tgz"," 文件的方式来引用，这样就好办了。",[27,185,186,187,190,191,193],{},"首先执行 ",[41,188,189],{},"npm adduser --registry=https:\u002F\u002Fmyregistry.example.com","，输入 Nexus 上具有上传 npm 包权限的用户名和密码，会在本地记录该用户的登录认证。然后在组件项目的 ",[41,192,57],{}," 中加入：",[66,195,197],{"className":68,"code":196,"language":70,"meta":71,"style":71},"{\n  \"publishConfig\": {\n    \"registry\": \"https:\u002F\u002Fmyregistry.example.com\u002Frepository\u002Fnpm-hosted\u002F\"\n  }\n}\n",[41,198,199,203,216,234,238],{"__ignoreMap":71},[75,200,201],{"class":77,"line":78},[75,202,82],{"class":81},[75,204,205,207,210,212,214],{"class":77,"line":85},[75,206,89],{"class":88},[75,208,209],{"class":92},"publishConfig",[75,211,96],{"class":88},[75,213,99],{"class":81},[75,215,102],{"class":81},[75,217,218,220,223,225,227,229,232],{"class":77,"line":105},[75,219,108],{"class":88},[75,221,222],{"class":111},"registry",[75,224,96],{"class":88},[75,226,99],{"class":81},[75,228,120],{"class":119},[75,230,231],{"class":123},"https:\u002F\u002Fmyregistry.example.com\u002Frepository\u002Fnpm-hosted\u002F",[75,233,127],{"class":119},[75,235,236],{"class":77,"line":130},[75,237,133],{"class":81},[75,239,240],{"class":77,"line":136},[75,241,139],{"class":81},[27,243,244,245,248],{},"然后执行 ",[41,246,247],{},"npm publish","，组件项目就会被上传到 Nexus 了。",[27,250,251,252,254],{},"在具体项目中，需要用到改组件的时候，在 ",[41,253,57],{}," 中这样引用：",[66,256,258],{"className":68,"code":257,"language":70,"meta":71,"style":71},"{\n  \"dependencies\": {\n    \"vue-footer\": \"https:\u002F\u002Fmyregistry.example.com\u002Frepository\u002Fnpm-hosted\u002Fexample-component\u002F-\u002Fexample-component-1.0.0.tgz\"\n  }\n}\n",[41,259,260,264,276,294,298],{"__ignoreMap":71},[75,261,262],{"class":77,"line":78},[75,263,82],{"class":81},[75,265,266,268,270,272,274],{"class":77,"line":85},[75,267,89],{"class":88},[75,269,93],{"class":92},[75,271,96],{"class":88},[75,273,99],{"class":81},[75,275,102],{"class":81},[75,277,278,280,283,285,287,289,292],{"class":77,"line":105},[75,279,108],{"class":88},[75,281,282],{"class":111},"vue-footer",[75,284,96],{"class":88},[75,286,99],{"class":81},[75,288,120],{"class":119},[75,290,291],{"class":123},"https:\u002F\u002Fmyregistry.example.com\u002Frepository\u002Fnpm-hosted\u002Fexample-component\u002F-\u002Fexample-component-1.0.0.tgz",[75,293,127],{"class":119},[75,295,296],{"class":77,"line":130},[75,297,133],{"class":81},[75,299,300],{"class":77,"line":136},[75,301,139],{"class":81},[27,303,304,305,308],{},"或者直接 ",[41,306,307],{},"npm install https:\u002F\u002Fmyregistry.example.com\u002Frepository\u002Fnpm-hosted\u002Fexample-component\u002F-\u002Fexample-component-1.0.0.tgz --save","。",[27,310,311,312,314,315,317],{},"组件更新通过修改 ",[41,313,57],{}," 里的版本号，然后 ",[41,316,247],{},"，然后具体项目中修改最后的版本号，重新安装即可。",[27,319,320],{},"另外由于这次都是用的最新的组件，也遇到了一个很大的坑。",[27,322,323,324,327,328,331,332,335,336,339,340,343,344,347,348,351,352,358,359,364],{},"我的项目都是基于 Nuxt.js 来搞的，Nuxt.js 的框架用起来更爽，ssr 性能也比 vue 原生的要高。有一个问题，组件项目在 webpack 打包的时候，默认是不支持 Nuxt 的 SSR 的，用了 ",[41,325,326],{},"vue-style-loader"," 之后，里面会有多个地方用到了 ",[41,329,330],{},"document","。如果需要同时支持 Browser 和 SSR，需要再建一个 SSR 的 webpack config，将 ",[41,333,334],{},"target"," 设为 ",[41,337,338],{},"node","，并且 ",[41,341,342],{},"vue-loader"," 的 ",[41,345,346],{},"options"," 中需要加入 ",[41,349,350],{},"optimizeSSR: false","，这个是因为尤大在最近的某个版本中针对 SSR 做了一些优化，但是在 Nuxt 的 SSR 中会有些问题，具体可以参见 ",[353,354,355],"a",{"href":355,"rel":356},"https:\u002F\u002Fgithub.com\u002Fnuxt\u002Fnuxt.js\u002Fissues\u002F2565",[357],"nofollow"," ，找了很久找到了这个 issue，追踪了下，尤大貌似在最近的 ",[353,360,363],{"href":361,"rel":362},"https:\u002F\u002Fgithub.com\u002Fvuejs\u002Fvue\u002Fcommit\u002F9b22d86ab315a3c6061a6a4776eab1964304f92e",[357],"v2.5.17-beta.0"," 中已经修复了这个问题，具体等 release 版发布之后再试下。在 Nuxt 中，创建一个 plugin，直接引用生成的 SSR 版本的文件即可。",[66,366,370],{"className":367,"code":368,"language":369,"meta":71,"style":71},"language-javascript shiki shiki-themes material-theme-lighter github-light github-dark","import ExampleComponent from 'example-component\u002Fdist\u002Fssr.js'\nimport Vue from 'vue'\n\nVue.use(ExampleComponent)\n","javascript",[41,371,372,394,410,416],{"__ignoreMap":71},[75,373,374,378,382,385,388,391],{"class":77,"line":78},[75,375,377],{"class":376},"sVHd0","import",[75,379,381],{"class":380},"su5hD"," ExampleComponent ",[75,383,384],{"class":376},"from",[75,386,387],{"class":119}," '",[75,389,390],{"class":123},"example-component\u002Fdist\u002Fssr.js",[75,392,393],{"class":119},"'\n",[75,395,396,398,401,403,405,408],{"class":77,"line":85},[75,397,377],{"class":376},[75,399,400],{"class":380}," Vue ",[75,402,384],{"class":376},[75,404,387],{"class":119},[75,406,407],{"class":123},"vue",[75,409,393],{"class":119},[75,411,412],{"class":77,"line":105},[75,413,415],{"emptyLinePlaceholder":414},true,"\n",[75,417,418,421,424,428],{"class":77,"line":130},[75,419,420],{"class":380},"Vue",[75,422,423],{"class":81},".",[75,425,427],{"class":426},"sGLFI","use",[75,429,430],{"class":380},"(ExampleComponent)\n",[27,432,433,434,343,437,440,441,444,445,448],{},"在 ",[41,435,436],{},"nuxt.config.js",[41,438,439],{},"plugins"," 中直接加入 ",[41,442,443],{},"'~plugins\u002Fcomponents-plugin.js'"," 即可。网上大部分解决方案是引用的时候将组件项目设置为 ",[41,446,447],{},"ssr: false","，其实是治标不治本，放弃了该组件在服务端的渲染，不可取。",[31,450,452],{"id":451},"基于-docker-的快速部署","基于 Docker 的快速部署",[27,454,455],{},"使用 Docker 也快 1 年了，基本上从开始用上 Docker 之后，就爱不释手了，大大缩短了发布时间，减少了运维成本。",[27,457,458],{},"目前我的项目都是部署在阿里云上，基于阿里云的容器集群方案，前面通过 SLB，后面横向部署多台机器。不多说，贴下 Dockerfile：",[66,460,464],{"className":461,"code":462,"language":463,"meta":71,"style":71},"language-dockerfile shiki shiki-themes material-theme-lighter github-light github-dark","FROM node:8-alpine\n\nWORKDIR \u002Fapp\n\nCOPY package.json \u002Fapp\nCOPY yarn.lock \u002Fapp\nRUN npm config set registry https:\u002F\u002Fregistry.npm.taobao.org && yarn config set registry https:\u002F\u002Fregistry.npm.taobao.org && yarn install\nCOPY . \u002Fapp\nRUN npm run build\n\nEXPOSE 6002\nENV SERVER_ENV $SERVER_ENV\nCMD [\"npm\", \"run\", \"start\"]\n","dockerfile",[41,465,466,475,479,487,491,499,507,516,524,532,537,546,555],{"__ignoreMap":71},[75,467,468,472],{"class":77,"line":78},[75,469,471],{"class":470},"sw1J6","FROM",[75,473,474],{"class":380}," node:8-alpine\n",[75,476,477],{"class":77,"line":85},[75,478,415],{"emptyLinePlaceholder":414},[75,480,481,484],{"class":77,"line":105},[75,482,483],{"class":470},"WORKDIR",[75,485,486],{"class":380}," \u002Fapp\n",[75,488,489],{"class":77,"line":130},[75,490,415],{"emptyLinePlaceholder":414},[75,492,493,496],{"class":77,"line":136},[75,494,495],{"class":470},"COPY",[75,497,498],{"class":380}," package.json \u002Fapp\n",[75,500,502,504],{"class":77,"line":501},6,[75,503,495],{"class":470},[75,505,506],{"class":380}," yarn.lock \u002Fapp\n",[75,508,510,513],{"class":77,"line":509},7,[75,511,512],{"class":470},"RUN",[75,514,515],{"class":380}," npm config set registry https:\u002F\u002Fregistry.npm.taobao.org && yarn config set registry https:\u002F\u002Fregistry.npm.taobao.org && yarn install\n",[75,517,519,521],{"class":77,"line":518},8,[75,520,495],{"class":470},[75,522,523],{"class":380}," . \u002Fapp\n",[75,525,527,529],{"class":77,"line":526},9,[75,528,512],{"class":470},[75,530,531],{"class":380}," npm run build\n",[75,533,535],{"class":77,"line":534},10,[75,536,415],{"emptyLinePlaceholder":414},[75,538,540,543],{"class":77,"line":539},11,[75,541,542],{"class":470},"EXPOSE",[75,544,545],{"class":380}," 6002\n",[75,547,549,552],{"class":77,"line":548},12,[75,550,551],{"class":470},"ENV",[75,553,554],{"class":380}," SERVER_ENV $SERVER_ENV\n",[75,556,558,561,564,567,570,573,575,578],{"class":77,"line":557},13,[75,559,560],{"class":470},"CMD",[75,562,563],{"class":380}," [",[75,565,566],{"class":123},"\"npm\"",[75,568,569],{"class":380},", ",[75,571,572],{"class":123},"\"run\"",[75,574,569],{"class":380},[75,576,577],{"class":123},"\"start\"",[75,579,580],{"class":380},"]\n",[27,582,583,584,587,588,590],{},"记得在 ",[41,585,586],{},".dockerignore"," 文件中把 ",[41,589,47],{}," 目录加上，在 COPY 的时候不进行复制，而是在 docker 环境中重新获取。",[27,592,593,594,596,597,600],{},"在项目的 ",[41,595,57],{}," 中配置好 ",[41,598,599],{},"deploy"," 命令：",[66,602,604],{"className":68,"code":603,"language":70,"meta":71,"style":71},"{\n  \"scripts\": {\n    \"deploy\": \"docker build -t registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:$npm_package_version -t registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:latest . && docker push registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:$npm_package_version && docker push registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:latest\"\n  }\n}\n",[41,605,606,610,623,640,644],{"__ignoreMap":71},[75,607,608],{"class":77,"line":78},[75,609,82],{"class":81},[75,611,612,614,617,619,621],{"class":77,"line":85},[75,613,89],{"class":88},[75,615,616],{"class":92},"scripts",[75,618,96],{"class":88},[75,620,99],{"class":81},[75,622,102],{"class":81},[75,624,625,627,629,631,633,635,638],{"class":77,"line":105},[75,626,108],{"class":88},[75,628,599],{"class":111},[75,630,96],{"class":88},[75,632,99],{"class":81},[75,634,120],{"class":119},[75,636,637],{"class":123},"docker build -t registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:$npm_package_version -t registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:latest . && docker push registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:$npm_package_version && docker push registry.cn-hangzhou.aliyuncs.com\u002Fyour-name\u002Fexample-project:latest",[75,639,127],{"class":119},[75,641,642],{"class":77,"line":130},[75,643,133],{"class":81},[75,645,646],{"class":77,"line":136},[75,647,139],{"class":81},[27,649,650,651,654],{},"在阿里云的容器镜像服务中建好镜像，便可以部署上去了。之前我是直接通过绑定 gitlab，在代码更新后，触发阿里云镜像服务在线构建，但是我们采用了私有的 npm 仓库的话，就比较麻烦了，还得配置 Nexus 账号，索性直接在本地构建，上传的网速也不是问题。在阿里云的容器服务中创建好应用，设置好触发器，在镜像更新后触发重新部署，就大功告成了。如果有多台机器，在调度配置中配置好“平滑升级”，会在同一服务的多个容器升级的时候，保证当前一批或者一个容器升级或者更新成功（健康检查成功）之后，再来更新或者升级下一批容器，也就是“滚动发布”。之后只需要 ",[41,652,653],{},"npm run deploy","，喝杯咖啡 ☕️，就完成了所有的部署工作了。方便、快捷、不易出错。",[27,656,657],{},"最近看了篇文章，里面有句话：“这世界上肯定存在让人上瘾的代码”，提出了“技术多巴胺”这个说法。而此刻的我，就仿佛打了几针“技术多巴胺”一样，很兴奋，一点睡意都没有。",[659,660,661],"style",{},"html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sseR_, html code.shiki .sseR_{--shiki-light:#9C3EDA;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":71,"searchDepth":85,"depth":85,"links":663},[664,665],{"id":33,"depth":105,"text":33},{"id":451,"depth":105,"text":452},null,"2018-04-14",false,"md",{},"\u002Fposts\u002F2018\u002Ffrontend-components-and-docker-deploy",{"text":673,"minutes":674,"time":675,"words":676},"10 min read",9.455,567300,1891,{"title":22,"description":29},{"loc":671},"posts\u002F2018\u002F20180414.frontend-components-and-docker-deploy",[681,682,683,684],"技术","前端","Docker","DevOps","凌晨","天气🌧","9_mH8lcdetq97RzpovxCwJ60jWmSz7r17jZvBEuf42s",[689,695],{"title":690,"path":691,"stem":692,"date":693,"description":694,"children":-1},"日记 - 20180419","\u002Fposts\u002F2018\u002Fdiary-20180419","posts\u002F2018\u002F20180419.diary-20180419","2018-04-19","我发现，洗澡的那段时间是我的贤者时间。",{"title":696,"path":697,"stem":698,"date":699,"description":700,"children":-1},"Maven 项目 Docker 一键发布配置","\u002Fposts\u002F2018\u002Fdockerfile-maven","posts\u002F2018\u002F20180412.dockerfile-maven","2018-04-12","Docker 用了很久了，之前 Maven 项目一直用的docker-maven-plugin，但是作者目前已经不推荐使用这种方式了，该项目已经不再更新功能，只提供 bugfix。他们的新项目叫做dockerfile-maven，配置上有些不同，之前一直没时间去更新，最近的一个项目中，采用了最新的插件，中间也踩过不少坑，刚刚终于都搞定了，记录一下。",1777580280625]