使用 Clojure 建立个人网站

首先 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"]

同时项目中的图标也做相应的更换。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181024G21XXL00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券