首先 docker 化数据库,你要停掉你本机的数据库,否则会冲突。 同时我们把暴露出的端口改成 5433
➜ soul-talkgit:(master) ✗ docker run-it--namepg-dev-p5433:5432-ePOSTGRES_USER=jiesoul-ePOSTGRES_PASSWORD=12345678-ePOSTGRES_DB=soul_talk-dpostgres:10
4ce3b4bfac22df6086efcfe907d0adba39121c9e974a3557d06d30dc9b327ac9
➜ soul-talkgit:(master) ✗ dockerps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4ce3b4bfac22 postgres"docker-entrypoint.s…"5seconds ago Up3seconds.0.0.0:5433->5432/tcp pg-dev
现在我们要修改一个我们的数据库连接的配置,我将使用 jdbc 字符串的形式来连接,同时把 ragtime 的配置也称到这里,首先修改 env/dev/resources 目录下的 config.edn ,同时为了区分开发和生产模式我们把开发模式的端口改成了 3001:
{:dev true
:port 3001
:database-url "jdbc:postgresql://localhost:5433/soul_talk?user=jiesoul&password=12345678"
:migrations "migrations"}
下面我们来修改 ragtime 的配置,我们新建 soul-talk.my-migrations, 在里面加入相应的函数:
(nssoul-talk.my-migrations
(:require[ragtime.jdbc:asragtime]
[ragtime.repl:asrepl]
[clojure.string:refer[join]]
[soul-talk.config:refer[env]]
[taoensso.timbre:aslog]))
(defmigrations
{"migrate"
(fn[config_]
(repl/migrateconfig))
"rollback"
(fn[config_]
(repl/rollbackconfig))})
(defnmigrations?[[args]]
(contains?(set(keysmigrations))args))
(defnmigrate
"args - vector of arguments e.g: [\"migrate\" \"001\"]
opts - map of options specifying the database configuration.
:database-url database url
:migration-dir migration file directory"
[argsopts]
(when-not(migrations?args)
(throw
(IllegalArgumentException.
(str"不能识别参数:"(firstargs)
", 有效的参数是:"(join","(keysmigrations))))))
(let[config{:datastore(ragtime/sql-database{:connection-uri(:database-urlopts)})
:migrations(ragtime/load-resources(:migrationsopts))}]
((getmigrations(firstargs))configargs)))
然后我们修改 env/clj 下的 dev 命名空间,删除我们原来的 config 定义,并加入新的函数:
(nsdev
(:require[clojure.pprint:refer[pprint]]
[clojure.tools.namespace.repl:astn]
[figwheel:refer[start-fwstop-fwcljs]]
[soul-talk.config:refer[env]]
[soul-talk.models.db:refer[*db*]]
[soul-talk.core]
[mount.core:asmount]
[mount-up.core:asmu]
[soul-talk.my-migrations:asmy-migrations]))
(defnmigrate[args]
(my-migrations/migrateargs(select-keysenv[:database-url:migrations])))
然后我们就可以通过 repl 来运行了:
=> (dev)
2018-10-1723:01:37,091 [nREPL-worker-0] INFO org.eclipse.jetty.util.log-Logging initialized @62503ms
2018-10-1723:01:44,816 [nREPL-worker-0] INFO compojure.api.coercion.schema-:schema coercion enabledincompojure.api
2018-10-1723:01:45,513 [nREPL-worker-0] INFO compojure.api.coercion.spec-:spec coercion enabledincompojure.api
2018-10-1723:01:47,120 [nREPL-worker-0] INFO compojure.api.swagger-:spec swagger generation enabledincompojure.api
=>#namespace[dev]
=> (go)
2018-10-1723:02:15,303 [nREPL-worker-0] INFO mount-up.core->> starting..#'soul-talk.config/env
2018-10-1723:02:15,372 [nREPL-worker-0] INFO mount-up.core->> starting..#'soul-talk.models.db/*db*
2018-10-1723:02:15,609 [nREPL-worker-0] INFO mount-up.core->> starting..#'soul-talk.core/init-app
18-10-1715:02:15 MacBook-Pro.local INFO [soul-talk.env:8]-====[soul-talk started successfully]====
2018-10-1723:02:15,650 [nREPL-worker-0] INFO mount-up.core->> starting..#'soul-talk.core/system
2018-10-1723:02:15,701 [nREPL-worker-0] INFO org.eclipse.jetty.server.Server-jetty-9.2.24.v20180105
=> :ready
2018-10-1723:02:15,921 [nREPL-worker-0] INFO o.e.jetty.server.ServerConnector-Started ServerConnector@1f450af1
2018-10-1723:02:15,922 [nREPL-worker-0] INFO org.eclipse.jetty.server.Server-Started @101336ms
=> (migrate ["migrate"])
Applying001-user
Applying002-posts
Applying003-categories
Applying004-tags
Applying005-posts_tags
Applying006-comments
=> nil
=> (migrate ["rollback"])
Rolling back006-comments
=> nil
=> (migrate ["migrate"])
Applying006-comments
=> nil
这样我们的开发模式就可以运行了,我们的数据库现在运行在 docker 上。
接下来我们要修改项目的 docker配置文件,以便于我们在生产环境可以先运行 ragtime 的数据库操作,再运行项目,新建 entrypoint.sh 文件,这里命令让我们在生产环境先更新数据库,然后再启动:
#!/bin/sh
if["$1"='soul-talk'] ;then
java-jar/app/soul-talk.jar migrate
exec java-jar/app/soul-talk.jar"$@"
fi
exec"$@"
修改 Dockerfile 文件:
# 基础依赖
FROMjava:8-alpine
# 个人信息
MAINTAINERjiesoul
# 项目 jar 复制到容器下
ADDtarget/soul-talk.jar /app/soul-talk.jar
# 复制启动脚本
COPYentrypoint.sh /app/entrypoint.sh
# 给启动脚本加可执行权限
RUNchmod +x /app/entrypoint.sh
# 端口
EXPOSE3000
# 入口
ENTRYPOINT[ "/app/entrypoint.sh" ]
# 运行命令
CMD[ "soul-talk" ]
然后修改 project.clj 的版本号:
defprojectsoul-talk"0.1.1"
最后构建和推送,依次运行下面的命令:
# 打包
lein uberjar
# 构建
lein docker build
# 提交到 docker hub
lein docker push
接下来我们要把整个项目容器化,我们要使用 docker 的 swarm 模式,首先在项目目录下新建 docker-compose.yml 文件:
# 配置文件版本
version:'3'
# 服务
services:
# 数据
db:
# 镜像
image:postgres:10
# 存储 引用下面的
volumes:
-db-data:/var/lib/postgresql/data
# 端口 前面的表示暴露出的端口,可以在主机访问,后面是容器内的端口
ports:
-"5432:5432"
# 环境变量配置 对应下面的数据库用户名、密码、数据库名称
environment:
POSTGRES_USER:jiesoul
POSTGRES_PASSWORD:12345678
POSTGRES_DB:soul_talk
# 应用
web:
# 应用依赖上面的数据库服务
depends_on:
-db
image:jiesoul/soul-talk:0.1.1
ports:
-"3000:3000"
environment:
DATABASE_URL:jdbc:postgresql://db/soul_talk?user=jiesoul&password=12345678
#存储
volumes:
db-data:
更多详细的配置请参考 docker 的官网。 这是在本地运行时的配置,如果在服务器上,请修改自己的数据库配置,最起码密码不可能是这样的。还要注意 web 下的数据库配置,url 是 db,表示上面的服务。
然后在项目目录下的命令行运行,初始化 swarm :
➜ soul-talkgit:(master) ✗ docker swarm init
Swarm initialized: currentnode(wbr4xgl1jnggvzb7o95bj0p73) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join--tokenSWMTKN-1-4non11pozodrb2idowtcgfbr5ygi6qi6dnx64a7woeeswlti8s-908pw83gvz0yn5alox4hos5ic192.168.65.3:2377
To add a manager to this swarm, run'docker swarm join-token manager'and follow the instructions.
然后运行命令,启动服务:
➜ soul-talkgit:(master) ✗ docker stack deploy-cdocker-compose.yml soultalkapp
Ignoring unsupported options:restart
Creating network soultalkapp_default
Creatingservicesoultalkapp_db
Creatingservicesoultalkapp_soul-talk
查看:
➜ soul-talkgit:(master) ✗ dockerservicels
ID NAME MODE REPLICAS IMAGE PORTS
tjm009m1kxpj soultalk_db replicated1/1 postgres:10 *:5432->5432/tcp
q5apeo92lgee soultalk_web replicated1/1 jiesoul/soul-talk:0.1.1 *:3000->3000/tcp
删除所有不在运行的容器
dockerrm$(docker container ls -f "status=exited" -q)
这样就可以在服务器上部署了。
下面我们要在解决一些 bug,我们发现在打包后,发现写文章的页面是空白的,有错误,原因是在 cljs 在编译的高级选项是 :optimizations :advanced 时,google 的编译器会重新分配变量名,这样 simplemde 里的变量就找不到了,所以我们我们要把这些第三方库排除在外,所以我们要在 project.clj 中加入配置:
:profiles
{:uberjar
{:omit-sourcetrue
:prep-tasks["compile"["cljsbuild""once""prod"]]
:cljsbuild
{:builds
{:prod
{:source-paths["src/cljs""src/cljc""env/prod/cljs"]
:compiler{:output-to"resources/public/js/main.js"
:externs["public/jslib/simplemde.min.js"
"public/jslib/highlight.js"
"public/jslib/codemirror.js"]
:closure-warnings{:externs-validation:off
:non-standard-jsdoc:off}
:optimizations:advanced
:pretty-printfalse}}}}
:externs 表示排除 simplemde,highlight 和 codemirror。closure-warnings 里的选项表示关闭第三库的警告信息。
然后我们在 resources/public 新建 jslib 目录用来存放第三方 js 库。请自行下载这些 js 库。
resources/public/jslib
├── codemirror.js
├── highlight.min.js
└── simplemde.min.js
然后修改 home.html:
{% script "/jslib/simplemde.min.js" %}
{% script "/jslib/codemirror.js" %}
{% script "/jslib/highlight.min.js" %}
然后是我们的 markdown 编辑器里面的图标并不能点击,原因是 simplemde 不能和fontawesome 5.X ,所以我们要把 fontawesome 换成 4.7 版本:
[org.webjars/font-awesome"4.7.0"]
同时项目中的图标也做相应的更换。
领取专属 10元无门槛券
私享最新 技术干货