Skip to content

Commit

Permalink
- Update Dockerfile with multistage build
Browse files Browse the repository at this point in the history
- Provide docker-compose with default services
- Provide default docker-compose django settings
- Provide simple nginx reverse proxy
  • Loading branch information
udgover committed Feb 5, 2021
1 parent 7b14a40 commit 3f46f8f
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 50 deletions.
78 changes: 29 additions & 49 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,52 +1,32 @@
# Dockerfile for FIR development instance
# written by Robert Haist
#
# Mostly based on the ubuntu image by Kyle Maxwell
#
# build with the command:
#
# sudo docker build -t fir .
# sudo docker run -it -p 8000:8000 fir
#
# then access http://localhost:8000 in your browser

# MAINTAINER Robert Haist, SleuthKid@mailbox.org
FROM alpine:3.7

RUN apk add --update \
python \
python-dev \
py-pip \
build-base \
git \
libxml2 \
FROM python:2.7-alpine AS builder
WORKDIR /app
COPY . /app
RUN apk add --update python-dev \
libxml2-dev \
libxslt \
libxslt-dev \
postgresql-dev \
&& rm -rf /var/cache/apk/*

RUN addgroup fir && \
adduser -D -G fir -s /sbin/nologin fir

WORKDIR /app

RUN git clone https://github.com/certsocietegenerale/FIR.git && \
chown -R fir:fir /app/FIR && \
cd FIR && \
pip install -r requirements.txt && \
cp fir/config/installed_apps.txt.sample fir/config/installed_apps.txt

USER fir
ENV HOME /app/FIR
ENV USER fir

WORKDIR /app/FIR

RUN ./manage.py migrate && \
./manage.py loaddata incidents/fixtures/seed_data.json && \
./manage.py loaddata incidents/fixtures/dev_users.json

build-base \
mariadb-dev \
musl-dev \
gcc && \
pip install virtualenv && \
virtualenv venv && \
source venv/bin/activate && \
find . -name requirements.txt -exec pip install -r {} \; && \
rm -rf .env .git .travis.yml docker Procfile README.md requirements.txt runtime.txt && \
mv fir/config/installed_apps.txt.sample fir/config/installed_apps.txt && \
deactivate

FROM python:2.7-alpine AS fir
COPY --from=builder /app /app
RUN apk add libxml2 libxslt mariadb-connector-c && \
rm -rf /var/cache/apk/* && \
wget -O /bin/wait-for https://raw.githubusercontent.com/eficode/wait-for/master/wait-for && \
chmod +x /bin/wait-for

WORKDIR /app/
ENV VIRTUAL_ENV /app/venv
ENV PATH /app/venv/bin:$PATH
ENV HOME /app/
EXPOSE 8000
ENTRYPOINT ["/app/FIR/manage.py"]
CMD ["runserver", "0.0.0.0:8000"]
ENTRYPOINT ["/app/manage.py"]
CMD ["runserver", "--settings", "fir.config.production", "0.0.0.0:8000"]
14 changes: 14 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Quick Start

```
docker-compose build
docker-compose up -d
```

Browse to http://localhost and log in with default credentials admin:admin or dev:dev

Enjoy!

# Customization.

If you need to change settings related to mysql or redis, you can edit fir.env file and set accordingly. These environments variable are provided to the container and used in composeprod.py file which corresponds to the default settings for django
102 changes: 102 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
version: '3.4'

networks:
backend.fir:

volumes:
static-content:

services:
fir:
image: fir:latest
build:
context: ../
dockerfile: docker/Dockerfile
entrypoint: /bin/sh
command: -c "wait-for -t 10 fir_db:3306 && python manage.py migrate && python manage.py loaddata incidents/fixtures/*.json && python manage.py collectstatic --no-input && python manage.py runserver 0.0.0.0:8000"
container_name: fir
hostname: fir
depends_on:
- fir_db
- fir_redis
env_file:
- fir.env
networks:
backend.fir:
# ports:
# - 8000:8000
expose:
- 8000
volumes:
- /tmp/uploads:/app/uploads
- static-content:/var/www/static

fir_db:
image: mariadb
container_name: fir_db
hostname: fir_db
networks:
backend.fir:
expose:
- 3306
volumes:
- /tmp/data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: toor
MYSQL_DATABASE: fir
MYSQL_USER: fir
MYSQL_PASSWORD: fir

fir_redis:
image: "redis:alpine"
container_name: fir_redis
hostname: fir_redis
networks:
backend.fir:
expose:
- 6379

fir_celery_worker:
image: fir:latest
entrypoint: /bin/sh
command: -c "wait-for -t 10 fir_redis:6379 && wait-for -t 30 fir:8000 -- celery -A fir_celery.celeryconf.celery_app worker -l debug"
container_name: fir_celery_worker
hostname: fir_celery_worker
depends_on:
- fir
- fir_db
- fir_redis
env_file:
- fir.env
networks:
backend.fir:

fir_celery_beat:
image: fir:latest
entrypoint: /bin/sh
command: -c "wait-for -t 10 fir_redis:6379 && wait-for -t 30 fir:8000 -- celery -A fir_celery.celeryconf.celery_app beat -l debug"
container_name: fir_celery_beat
hostname: fir_celery_beat
depends_on:
- fir
- fir_db
- fir_redis
env_file:
- fir.env
networks:
backend.fir:

fir_web:
image: nginx
container_name: fir_web
hostname: fir_web
depends_on:
- fir
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- static-content:/usr/share/nginx/html:ro
ports:
- 80:80
networks:
backend.fir:

18 changes: 18 additions & 0 deletions docker/fir.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Default configuration
HOME=/app/FIR

DJANGO_SETTINGS_MODULE=fir.config.composeprod

ALLOWED_HOSTS=localhost,127.0.0.1
DEBUG=true

# Secret key
SECRET_KEY="not so secret"

# Database configuration
DATABASE_URL=mysql://fir:fir@fir_db:3306/fir

# Redis configuration
REDIS_HOST=fir_redis
REDIS_PORT=6379
REDIS_DB=0
34 changes: 34 additions & 0 deletions docker/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
worker_processes 1;

events { worker_connections 1024; }

http {

include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;

upstream fir_app {
server fir:8000;
}

server {
listen 80;

location / {
proxy_pass http://fir_app;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}

location /static/ {
alias /usr/share/nginx/html/;
}


}

}
100 changes: 100 additions & 0 deletions fir/config/composeprod.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# This is the production settings !
# All settings that do not change across environments should be in 'fir.settings.base'
from fir.config.base import *

from environs import Env

env = Env()
env.read_env(env.str('ENV_PATH', '.env'), recurse=False)

################################################################
##### Change these values
################################################################

# Configure ALLOWED_HOSTS
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', ['localhost', '127.0.0.1'])

# Configure SECRET KEY
SECRET_KEY = env('SECRET_KEY', 'I 4m tH3 d3f4u17 s3cr37')


# DATABASES SETTINGS

# If you have to deal with special characters in your password, use urlencode:
# https://django-environ.readthedocs.io/en/latest/#using-unsafe-characters-in-urls
DATABASES = {
# reads var DATABASE_URL. If not set defaults to sqlite
# To use mysql backend, you can set the following env for example
# DATABASE_URL=mysql://fir:fir@fir_db:3306/fir
'default': env.dj_db_url('DATABASE_URL', default='sqlite:////tmp/fir.sqlite')
}

# SMTP SETTINGS
EMAIL_HOST = env('EMAIL_HOST', 'SMTP.DOMAIN.COM')
EMAIL_PORT = env.int('EMAIL_PORT', 25)

# Uncomment this line to set a different reply-to address when sending alerts
#REPLY_TO = env.str('REPLY_TO', 'to@domain')
EMAIL_FROM = env.str('EMAIL_FROM', '"NAME" <from@ndomain>')

# Uncomment these lines if you want additional CC or BCC for all sent emails
#EMAIL_CC = env.list('EMAIL_CC', ['cc@domain'])
#EMAIL_BCC = env.list('EMAIL_BCC', ['bcc@domain'])


# REDIS SETTINGS
# Uncomment the following lines if you want to run celery tasks
REDIS_HOST = env.str('REDIS_HOST', 'fir_redis')
REDIS_PORT = env.int('REDIS_PORT', 6379)
REDIS_DB = env.int('REDIS_DB', 0)

STATIC_ROOT = '/var/www/static'

################################################################

# False if not in os.environ
DEBUG = env.bool('DEBUG', default=False)

TEMPLATES[0]['OPTIONS']['debug'] = DEBUG

# List of callables that know how to import templates from various sources.
# In production, we want to cache templates in memory
TEMPLATES[0]['OPTIONS']['loaders'] = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)


# TEMPLATES[0]['OPTIONS']['loaders'] = (
# ('django.template.loaders.cached.Loader', (
# 'django.template.loaders.filesystem.Loader',
# 'django.template.loaders.app_directories.Loader',
# )),
# )

LOGGING = {
'version': 1,
'formatters': {
'verbose': {
'format': '%(asctime)s: %(module)s %(filename)s:%(lineno)d(%(funcName)s)\n%(message)s'
},
},
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': os.path.join(BASE_DIR, 'logs', 'errors.log'),
'formatter': 'verbose',
},
},
'loggers': {
'django.request': {
'handlers': ['file'],
'level': 'ERROR',
'propagate': True,
},
},
}

# External URL of your FIR application (used in fir_notification to render full URIs in templates)
#EXTERNAL_URL = 'http://fir.example.com'
5 changes: 4 additions & 1 deletion fir/config/installed_apps.txt.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
fir_api
fir_alerting
fir_todos
fir_nuggets
fir_api
fir_threatintel
fir_artifacts_enrichment
fir_abuse
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
cssselect==0.9.1
dj-database-url==0.4.1
dj-email-url
environs
future
mysqlclient
Django==1.11
django-filter==0.14.0
djangorestframework==3.4.6
Expand Down

0 comments on commit 3f46f8f

Please sign in to comment.