diff --git a/.gitignore b/.gitignore index 31b484c..f236541 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ get_api_key.py -quotes.db* -settings.cfg diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1ffb7c6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM node:alpine as builder + +WORKDIR /build +COPY frontend/package.json frontend/package-lock.json ./ + +RUN npm install && mkdir /ng-app && cp -r node_modules/ /ng-app + +WORKDIR /ng-app +COPY frontend . + +RUN $(npm bin)/ng build --prod --build-optimizer + +FROM nginx:alpine + +COPY nginx/nginx.conf /etc/nginx/nginx.conf + +COPY --from=builder /ng-app/dist /srv/http + +EXPOSE 80 + +ENTRYPOINT ["nginx", "-g", "daemon off;"] diff --git a/api/Dockerfile b/api/Dockerfile new file mode 100644 index 0000000..9f89110 --- /dev/null +++ b/api/Dockerfile @@ -0,0 +1,10 @@ +FROM python:alpine + +WORKDIR /app +COPY . . + +RUN pip install --no-cache-dir --requirement requirements.txt + +EXPOSE 5000 + +ENTRYPOINT ["python", "app.py"] diff --git a/api/app.py b/api/app.py index 3192b79..7528be4 100644 --- a/api/app.py +++ b/api/app.py @@ -1,3 +1,5 @@ +import os + import flask import flask_login import flask_restful @@ -10,7 +12,11 @@ from db import db, Quote app = flask.Flask(__name__) -app.config.from_envvar('SETTINGS') +app.config.update( + ERROR_404_HELP=False, + SQLALCHEMY_TRACK_MODIFICATIONS=False, + SQLALCHEMY_DATABASE_URI=os.getenv('SQLALCHEMY_DATABASE_URI'), + SECRET_KEY=os.getenv('SECRET_KEY')) db.init_app(app) db.create_all(app=app) @@ -105,6 +111,7 @@ class QuotesResource(flask_restful.Resource): if args['filter']: q = q.filter(Quote.text.ilike('%{}%'.format(args['filter']))) count = q.count() + # TODO: random order if args['sort_by']: col = getattr(Quote, args['sort_by'], None) if col: @@ -144,3 +151,7 @@ class QuotesResource(flask_restful.Resource): api.add_resource(QuoteResource, '/quotes/') api.add_resource(QuotesResource, '/quotes') + + +if __name__ == '__main__': + app.run(host='0.0.0.0', threaded=True, debug=False) diff --git a/api/requirements.txt b/api/requirements.txt new file mode 100644 index 0000000..61e7259 --- /dev/null +++ b/api/requirements.txt @@ -0,0 +1,5 @@ +Flask +Flask-Login +Flask-RESTful +Flask-SQLAlchemy +itsdangerous diff --git a/frontend/Makefile b/frontend/Makefile deleted file mode 100644 index 91b3e10..0000000 --- a/frontend/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -DESTINATION = /srv/http/quotes/quotes -BUILD_FLAGS = --prod --build-optimizer - -.PHONY: all quotes - -all: quotes - -quotes: - ng build $(BUILD_FLAGS) --output-path $(DESTINATION) diff --git a/frontend/src/app/services/quotes.service.ts b/frontend/src/app/services/quotes.service.ts index 07252b4..9246a02 100644 --- a/frontend/src/app/services/quotes.service.ts +++ b/frontend/src/app/services/quotes.service.ts @@ -23,7 +23,7 @@ export class QuotesService { filter = '', sortBy = 'id', sortOrder = 'desc', pageNumber = 0, pageSize = 10): Observable { - return this.http.get('/quotes/api/quotes', { + return this.http.get('/api/quotes', { observe: 'response', params: new HttpParams() .set('filter', filter) diff --git a/frontend/src/index.html b/frontend/src/index.html index fed848a..f40640b 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -3,7 +3,7 @@ Quotes - + diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..b56e5c8 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,64 @@ +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + gzip on; + + server { + listen 80; + server_name localhost; + + location / { + root /srv/http; + index index.html; + } + + location /api { + rewrite ^/api(/.*)$ $1 break; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_http_version 1.1; + tcp_nodelay on; + proxy_pass http://api:5000/; + } + + location ~ /\.ht { + deny all; + } + + error_page 404 /404.html; + location = /404.html { + root /usr/share/nginx/html; + } + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +}