diff --git a/.env.production.sample b/.env.production.sample index 4ee2faa..d7b5055 100644 --- a/.env.production.sample +++ b/.env.production.sample @@ -12,7 +12,7 @@ BASE_URL=http://localhost:3000 SECRET_KEY_BASE= ## PostgreSQL connection URL. -## Default: postgresql://postgres@postgres/postgres +## Default: postgresql://postgres/postgres?user=postgres # DATABASE_URL= ## Redis connection URL. diff --git a/Dockerfile b/Dockerfile index 74e4c48..9549880 100644 --- a/Dockerfile +++ b/Dockerfile @@ -97,11 +97,20 @@ RUN cd a2png && npm install COPY a2png /app/a2png RUN cd a2png && lein cljsbuild once main && lein cljsbuild once page +# build uberjar + +COPY project.clj /app/ +RUN lein deps + +COPY src /app/src +COPY resources /app/resources +RUN lein uberjar + # copy the rest of the source code COPY . /app -ENV DATABASE_URL "postgresql://postgres@postgres/postgres" +ENV DATABASE_URL "postgresql://postgres/postgres?user=postgres" ENV REDIS_URL "redis://redis:6379" # compile terminal.c @@ -125,6 +134,11 @@ COPY docker/nginx/asciinema.conf /etc/nginx/sites-available/default RUN mkdir -p /var/log/supervisor COPY docker/supervisor/asciinema.conf /etc/supervisor/conf.d/asciinema.conf +# add start script for Clojure app + +COPY docker/start.sh /app/start.sh +RUN chmod a+x /app/start.sh + VOLUME ["/app/log", "/app/uploads"] CMD ["/usr/bin/supervisord"] diff --git a/dev/resources/dev.edn b/dev/resources/dev.edn index cf8c240..0545cb2 100644 --- a/dev/resources/dev.edn +++ b/dev/resources/dev.edn @@ -1,12 +1,9 @@ {:components - {:file-store #var asciinema.component.local-file-store/local-file-store - :exp-set #var asciinema.component.mem-expiring-set/mem-expiring-set} + {:exp-set #var asciinema.component.mem-expiring-set/mem-expiring-set} :config {:http {:port 4000} :db {:uri "jdbc:postgresql://localhost:15432/asciinema_development?user=vagrant"} - :file-store - {:path "uploads/"} :png-gen {:bin-path "a2png/a2png.sh"}}} diff --git a/docker/nginx/asciinema.conf b/docker/nginx/asciinema.conf index 6e92331..2b8c371 100644 --- a/docker/nginx/asciinema.conf +++ b/docker/nginx/asciinema.conf @@ -2,6 +2,10 @@ upstream rails-server { server 127.0.0.1:3000 fail_timeout=0; } +upstream clj-server { + server 127.0.0.1:4000 fail_timeout=0; +} + server { listen 80 default_server; listen [::]:80 default_server; @@ -12,6 +16,10 @@ server { client_max_body_size 16m; + location ~ ^/a/[^.]+\.(json|png)$ { + try_files $uri $uri/index.html $uri.html @clj; + } + location / { try_files $uri $uri/index.html $uri.html @rails; } @@ -33,4 +41,13 @@ server { proxy_redirect off; error_page 500 502 504 /500.html; # Rails error pages } + + location @clj { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; + proxy_pass http://clj-server; + proxy_redirect off; + } } diff --git a/docker/start.sh b/docker/start.sh new file mode 100644 index 0000000..be59cea --- /dev/null +++ b/docker/start.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +export DATABASE_URL=jdbc:${DATABASE_URL} +export S3_ACCESS_KEY=${AWS_ACCESS_KEY_ID} +export S3_SECRET_KEY=${AWS_SECRET_ACCESS_KEY} +export A2PNG_BIN_PATH="/app/a2png/a2png.sh" + +exec java -server -Xmx3g -jar /app/target/uberjar/asciinema-0.1.0-SNAPSHOT-standalone.jar diff --git a/docker/supervisor/asciinema.conf b/docker/supervisor/asciinema.conf index 0857a41..0dd20d4 100644 --- a/docker/supervisor/asciinema.conf +++ b/docker/supervisor/asciinema.conf @@ -14,4 +14,12 @@ directory=/app stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:clj] +command=/app/start.sh +directory=/app +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 \ No newline at end of file diff --git a/resources/asciinema/system.edn b/resources/asciinema/system.edn index aa5b2c8..b7df1cc 100644 --- a/resources/asciinema/system.edn +++ b/resources/asciinema/system.edn @@ -2,7 +2,7 @@ {:http #var asciinema.component.yada-listener/yada-listener :db #var asciinema.component.db/hikaricp :ragtime #var duct.component.ragtime/ragtime - :file-store #var asciinema.component.s3-file-store/s3-file-store + :file-store #var asciinema.component.auto-file-store/auto-file-store :exp-set #var asciinema.component.redis-client/redis-client :png-gen #var asciinema.component.a2png/a2png :executor #var asciinema.component.fixed-thread-executor/fixed-thread-executor} @@ -20,13 +20,12 @@ :ragtime {:resource-path "asciinema/migrations"} :file-store - {:cred {:access-key s3-access-key - :secret-key s3-secret-key} - :bucket s3-bucket - :path-prefix "uploads/"} + {:path "uploads/" + :s3-bucket s3-bucket + :s3-cred {:access-key s3-access-key + :secret-key s3-secret-key}} :exp-set - {:host redis-host - :port redis-port} + {:uri redis-url} :png-gen {:bin-path a2png-bin-path} :executor diff --git a/src/asciinema/component/auto_file_store.clj b/src/asciinema/component/auto_file_store.clj new file mode 100644 index 0000000..e674537 --- /dev/null +++ b/src/asciinema/component/auto_file_store.clj @@ -0,0 +1,8 @@ +(ns asciinema.component.auto-file-store + (:require [asciinema.component.local-file-store :refer [local-file-store]] + [asciinema.component.s3-file-store :refer [s3-file-store]])) + +(defn auto-file-store [config] + (if (:s3-bucket config) + (s3-file-store config) + (local-file-store config))) diff --git a/src/asciinema/component/redis_client.clj b/src/asciinema/component/redis_client.clj index 07af0f6..da725a4 100644 --- a/src/asciinema/component/redis_client.clj +++ b/src/asciinema/component/redis_client.clj @@ -5,12 +5,12 @@ [com.stuartsierra.component :as component] [taoensso.carmine :as car])) -(defrecord RedisClient [host port] +(defrecord RedisClient [uri] component/Lifecycle (start [component] (if (:listener component) component - (let [conn {:pool {} :spec {:host host :port port}}] + (let [conn {:pool {} :spec {:uri uri}}] (assoc component :conn conn)))) (stop [component] (if (:conn component) @@ -24,5 +24,5 @@ (contains? [this value] (car/as-bool (car/wcar (:conn this) (car/exists value))))) -(defn redis-client [{:keys [host port]}] - (->RedisClient host port)) +(defn redis-client [{:keys [uri]}] + (->RedisClient uri)) diff --git a/src/asciinema/component/s3_file_store.clj b/src/asciinema/component/s3_file_store.clj index 3443dd0..8beec5c 100644 --- a/src/asciinema/component/s3_file_store.clj +++ b/src/asciinema/component/s3_file_store.clj @@ -60,5 +60,5 @@ (assoc :status 302) (update :headers assoc "location" url))))) -(defn s3-file-store [{:keys [cred bucket path-prefix]}] - (->S3FileStore cred bucket path-prefix)) +(defn s3-file-store [{:keys [s3-cred s3-bucket path]}] + (->S3FileStore s3-cred s3-bucket path)) diff --git a/src/asciinema/main.clj b/src/asciinema/main.clj index 7eecb3e..a283b17 100644 --- a/src/asciinema/main.clj +++ b/src/asciinema/main.clj @@ -27,13 +27,12 @@ (defn -main [& args] (binding [y/*exception-notifier* (create-exception-notifier)] - (let [bindings {'http-port (Integer/parseInt (:port env "3000")) + (let [bindings {'http-port (Integer/parseInt (:port env "4000")) 'db-uri (:database-url env) 's3-bucket (:s3-bucket env) 's3-access-key (:s3-access-key env) 's3-secret-key (:s3-secret-key env) - 'redis-host (:redis-host env "localhost") - 'redis-port (Integer/parseInt (:redis-port env "6379")) + 'redis-url (:redis-url env "redis://localhost") 'a2png-bin-path (:a2png-bin-path env "a2png/a2png.sh")} system (->> (load-system [(io/resource "asciinema/system.edn")] bindings) (component/start))]