Skip to content

Commit

Permalink
build: improve docker setup
Browse files Browse the repository at this point in the history
  • Loading branch information
engineervix committed Sep 1, 2024
1 parent c68a1b6 commit 7c10ce1
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 210 deletions.
70 changes: 53 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
FROM python:3.8-slim-bullseye
#################################################################################
# use node:14-bookworm as the base image for building the frontend
#################################################################################

FROM node:14-bookworm AS frontend-builder

# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json Gruntfile.js ./
RUN npm ci --no-optional --no-audit --progress=false --network=host

COPY ./tenlists/webapp/ten_lists/static/ ./tenlists/webapp/ten_lists/static/
RUN npm run build

#################################################################################
# use python:3.12-slim-bookworm as the base image for production and development
#################################################################################

FROM python:3.12-slim-bookworm AS production

# Add user that will be used in the container
RUN groupadd flask && \
Expand All @@ -21,29 +39,17 @@ ENV PYTHONUNBUFFERED=1 \
WEB_CONCURRENCY=3 \
PORT=8000 \
FLASK_CONFIGURATION=production \
FLASK_ENV=production \
# NODE_ENV=production \
USER=flask \
PATH=/home/flask/app/node_modules/.bin:$PATH
FLASK_ENV=production

# Install system dependencies
RUN apt-get update --yes --quiet && apt-get install --yes --quiet --no-install-recommends \
build-essential \
curl \
ffmpeg \
git \
libjpeg62-turbo-dev \
libmariadb-dev-compat libmariadb-dev \
libpq-dev \
libwebp-dev \
zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*

# install Node.js
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -
RUN apt install nodejs -y
RUN npm install -g grunt-cli

# Use user "flask" to run the build commands below and the server itself.
USER flask

Expand All @@ -60,11 +66,41 @@ RUN pip install --upgrade pip
COPY --chown=flask ./requirements.txt .
RUN pip install -r requirements.txt

# Copy build artifacts from frontend-builder stage
COPY --from=frontend-builder --chown=flask:flask /tenlists/webapp/ten_lists/static/css/custom.min.css /home/flask/app/tenlists/webapp/ten_lists/static/css/custom.min.css
COPY --from=frontend-builder --chown=flask:flask /tenlists/webapp/ten_lists/static/js/custom.min.js /home/flask/app/tenlists/webapp/ten_lists/static/js/custom.min.js
COPY --from=frontend-builder --chown=flask:flask /tenlists/webapp/ten_lists/static/vendors /home/flask/app/tenlists/webapp/ten_lists/static/vendors

# Copy the source code of the project into the container
COPY --chown=flask:flask . .

# Generate static assets
RUN npm run build

# Runtime command that executes when "docker run" is called
CMD "gunicorn tenlists.webapp.ten_lists:create_app()"


#################################################################################
# The next steps won't be run in production
#################################################################################

FROM production AS dev

# Swap user, so the following tasks can be run as root
USER root

# set environment variables
ENV NODE_MAJOR=14 \
PATH=/home/flask/app/node_modules/.bin:$PATH

# Install node (Keep the version in sync with the node container above)
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - && \
apt-get install -y nodejs
RUN npm install -g grunt-cli

# Restore user
USER flask

# Pull in the node modules for the frontend
COPY --chown=flask:flask --from=frontend-builder ./node_modules ./node_modules

# do nothing - exec commands elsewhere
CMD tail -f /dev/null
101 changes: 12 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ This project provides both a CLI (using [click](https://click.palletsprojects.co
> You can see the webapp in action [here](https://ten.dumela.cc/)
[![python3.8](https://img.shields.io/badge/python-3.8-brightgreen.svg)](https://python.org/)
[![CircleCI](https://circleci.com/gh/engineervix/ten-lists/tree/master.svg?style=svg)](https://circleci.com/gh/engineervix/ten-lists/tree/master)
[![Coverage Status](https://coveralls.io/repos/github/engineervix/ten-lists/badge.svg)](https://coveralls.io/github/engineervix/ten-lists)
[![Maintainability](https://api.codeclimate.com/v1/badges/0f58287b5eaf57213fa2/maintainability)](https://codeclimate.com/github/engineervix/ten-lists/maintainability)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/f566d7c0bd464cb2b17ef9604b61a748)](https://www.codacy.com/gh/engineervix/ten-lists/dashboard?utm_source=github.com&utm_medium=referral&utm_content=engineervix/ten-lists&utm_campaign=Badge_Grade)
Expand Down Expand Up @@ -66,10 +65,10 @@ Good to have if you'd like to hack on the project. Not required if you just wann

Upon cloning this repository (or forking + cloning your fork), navigate to the cloned project directory.

Then create the required environment variables file (`.env`) by making a copy of the provided sample file `.env.sample` and renaming it to `.dev.env`:
Then create the required environment variables file (`.env`) by making a copy of the provided sample file `env/.env.example` and renaming it to `env/.dev.env`:

```sh
cp -v .env.sample .env
cp -v env/.env.example env/.dev.env
```

> NOTE: If you're not using a docker-based deployment approach, then, for production, the file should be `.prod.env`, for staging `.stage.dev`
Expand All @@ -79,105 +78,29 @@ You should be able to run the project without updating anything. If you wanna up
Build the images and spin up the containers:

```sh
COMPOSE_PROJECT_NAME=tenlists docker-compose up -d --build
docker-compose up -d --build
```

When you run the above for the first time, it may take a while, depending on your internet connection speed.

Once the build is complete, you can check the logs for the `web` container via
If everything goes well, you should be able to get into the `web` container and access the shell.

```sh
docker-compose logs web
docker-compose exec web bash
```

If everything is ok, you should see something like this:

```console
tenlists-web-1 | tenlists :: ready
tenlists-web-1 | * Serving Flask app "tenlists.webapp.ten_lists" (lazy loading)
tenlists-web-1 | * Environment: development
tenlists-web-1 | * Debug mode: on
tenlists-web-1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
tenlists-web-1 | * Restarting with stat
tenlists-web-1 | * Debugger is active!
tenlists-web-1 | * Debugger PIN: 719-114-836
```

You can also check the logs for the `node` container via
Once you're in the container, run the following to simultaneously launch the Flask development server and the frontend tooling:

```sh
docker-compose logs node
inv start
```

If all's well, you should see something like this:

```console
tenlists-node-1 |
tenlists-node-1 | > ten-lists@0.6.2 start /usr/src/app
tenlists-node-1 | > grunt
tenlists-node-1 |
tenlists-node-1 | Running "clean:dist" (clean) task
tenlists-node-1 | >> 4 paths cleaned.
tenlists-node-1 |
tenlists-node-1 | Running "newer:copy" (newer) task
tenlists-node-1 |
tenlists-node-1 | Running "newer:copy:fa" (newer) task
tenlists-node-1 |
tenlists-node-1 | Running "copy:fa" (copy) task
tenlists-node-1 | Copied 8 files
tenlists-node-1 |
tenlists-node-1 | Running "newer-postrun:copy:fa:1:/usr/src/app/node_modules/grunt-newer/.cache" (newer-postrun) task
tenlists-node-1 |
tenlists-node-1 | Running "newer:copy:bootstrap" (newer) task
tenlists-node-1 |
tenlists-node-1 | Running "copy:bootstrap" (copy) task
tenlists-node-1 | Copied 10 files
tenlists-node-1 |
tenlists-node-1 | Running "newer-postrun:copy:bootstrap:2:/usr/src/app/node_modules/grunt-newer/.cache" (newer-postrun) task
tenlists-node-1 |
tenlists-node-1 | Running "newer:copy:jquery" (newer) task
tenlists-node-1 |
tenlists-node-1 | Running "copy:jquery" (copy) task
tenlists-node-1 | Copied 4 files
tenlists-node-1 |
tenlists-node-1 | Running "newer-postrun:copy:jquery:3:/usr/src/app/node_modules/grunt-newer/.cache" (newer-postrun) task
tenlists-node-1 |
tenlists-node-1 | Running "newer:copy:moment" (newer) task
tenlists-node-1 |
tenlists-node-1 | Running "copy:moment" (copy) task
tenlists-node-1 | Copied 5 files
tenlists-node-1 |
tenlists-node-1 | Running "newer-postrun:copy:moment:4:/usr/src/app/node_modules/grunt-newer/.cache" (newer-postrun) task
tenlists-node-1 |
tenlists-node-1 | Running "newer:cssmin" (newer) task
tenlists-node-1 |
tenlists-node-1 | Running "newer:cssmin:dist" (newer) task
tenlists-node-1 | No newer files to process.
tenlists-node-1 |
tenlists-node-1 | Running "newer:uglify" (newer) task
tenlists-node-1 |
tenlists-node-1 | Running "newer:uglify:dist" (newer) task
tenlists-node-1 | No newer files to process.
tenlists-node-1 |
tenlists-node-1 | Running "browserSync:dev" (browserSync) task
tenlists-node-1 | [Browsersync] Proxying: http://web:5000
tenlists-node-1 | [Browsersync] Access URLs:
tenlists-node-1 | -----------------------------------
tenlists-node-1 | Local: http://localhost:3000
tenlists-node-1 | External: http://151.26.0.3:3000
tenlists-node-1 | -----------------------------------
tenlists-node-1 | UI: http://localhost:3001
tenlists-node-1 | UI External: http://localhost:3001
tenlists-node-1 | -----------------------------------
tenlists-node-1 | [Browsersync] Watching files...
tenlists-node-1 |
tenlists-node-1 | Running "watch" task
tenlists-node-1 | Waiting...
tenlists-node-1 | [Browsersync] Reloading Browsers...
tenlists-node-1 | [Browsersync] Reloading Browsers...
```
You can access the dev server at <http://127.0.0.1:8000>.

You can access the dev server at <http://127.0.0.1:5000>.
> **Note**
>
> - The above is made possible by [Invoke](https://www.pyinvoke.org/), which is used extensively on this project to automate some tasks.
> Run `invoke -l` to see all available [Invoke](https://www.pyinvoke.org/) tasks. These are defined in the [tasks.py](tasks.py) file.
#### You need the MP3 files

Expand Down
25 changes: 5 additions & 20 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,17 @@ services:
web:
build:
context: .
dockerfile: ./docker/flask/Dockerfile
command: inv dev
args:
DEVELOPMENT: 1
target: dev
command: tail -f /dev/null
volumes:
- ./:/home/flask/app/
ports:
- 5000:5000
- 8000:8000
env_file:
- env/.dev.env
environment:
- FLASK_CONFIGURATION=development
- FLASK_ENV=development

node:
build:
context: .
dockerfile: ./docker/node/Dockerfile
depends_on:
- web
volumes:
- ./:/usr/src/app/
# http://jdlm.info/articles/2016/03/06/lessons-building-node-app-docker.html
- /usr/src/app/node_modules
command: npm start
ports:
- 3000:3000
# Expose browsersync UI: https://www.browsersync.io/docs/options/#option-ui
- 3001:3001
environment:
- NODE_ENV=development
2 changes: 2 additions & 0 deletions docker/Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
web: inv dev
frontend: npm run start
5 changes: 5 additions & 0 deletions docker/docker-compose-frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
web:
ports:
- 3000:3000 # browser-sync
- 3001:3001 # browser-sync UI
64 changes: 0 additions & 64 deletions docker/flask/Dockerfile

This file was deleted.

5 changes: 0 additions & 5 deletions docker/flask/entrypoint.sh

This file was deleted.

14 changes: 0 additions & 14 deletions docker/node/Dockerfile

This file was deleted.

5 changes: 5 additions & 0 deletions env/env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Note: No spaces around '=' sign and no quotes for righthand values.

# Docker
COMPOSE_DOCKER_CLI_BUILD=1
DOCKER_BUILDKIT=1
COMPOSE_PROJECT_NAME=tenlists

# Example commands to create a new secret key:
# openssl rand -hex 50
# $ python -c 'import random; import string; print("".join([random.SystemRandom().choice(string.digits + string.ascii_letters + string.punctuation) for i in range(100)]))'
Expand Down
9 changes: 8 additions & 1 deletion tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
@task
def dev(c):
"""run the Flask development server"""
c.run("python manage.py runserver --host 0.0.0.0", pty=True)
c.run("python manage.py runserver --host 0.0.0.0 --port 8000", pty=True)


@task
def start(c):
"""Run this in a container to fire up the Flask development server & frontend tools"""
# https://github.com/nickstenning/honcho
c.run("honcho -f docker/Procfile start", pty=True)


@task
Expand Down

0 comments on commit 7c10ce1

Please sign in to comment.