This is a small Quart app to render a #100DayOfCode markdown log as a HTML page. Quart is an async-enabled version of Flask.
I have also created a Gatsby site with the same functionality, because it is overkill to do the conversion from markdown to HTML on every request for content that is only updated once a day.
This app is designed to be pointed at the raw files of #100DayOfCode markdown journal repository. You can clone/fork @kallaway's original journal repo to start your log.
To find the URL for the raw files click one of the files and then the "Raw" button.
This will give you a URL like this:
You only need the part until the filename:
The app will generate a HTML based on the content of the Markdown files in the repo. You can see a live implementation on my website.
Requires a host (or local machine) with Docker installed.
If you have
docker installed, you don't really need to install anything.
All you need is to pull the Docker image.
$ docker pull tbrlpld/log100days
Depending on your OS and setup, you might have to run the docker with
If you try to run the app container with out configuring the app first, you will get an error message.
$ docker run tbrlpld/log100days ... KeyError: 'The environment variable SECRET_KEY is missing. Be sure to configure it and try again.'
To enable configuration of the app running in the container, we are using environment variables. The advantage over file based configuration is that environment variables can be created in the container in different ways.
You can pass environment variables to the container via the
or directly to the
docker run command.
Instead of creating each environment variable separately, you can also make use of environment files in either of these cases.
To make the environment variables easy to reuse, we use the environment file approach.
This can be done by creating a
.env file with the following content:
SECRET_KEY=this-needs-to-be-something-safe MARKDOWN_LOG_URL=https://raw.githubusercontent.com/kallaway/100-days-of-code/master/ HOME_URL=https://example.com
Make sure to use a safe value for the
SECRET_KEY environment variable and do not commit it to version control.
MARKDOWN_LOG_URL settings defines the repository where the markdown files can be found.
It does not have to be a GitHub repo.
Any URL which is extended with the Markdown filenames works.
HOME_URL defines which site the "Home" link in the navigation menu should point to.
If this setting is not defined, the menu entry is omitted.
Now the use of the environment file needs to be passed to docker.
To do so, just add the
env_file key to the
... env_file: - .env ...
The more Flask typical way of configuring through a
config.py file in the "instance" folder is still possible.
The values defined in the
config.py will override what is defined in the environment variables.
Since the configuration file is a Python file, use the appropriate syntax to define the values. See the Flask documentation on more information on how to use these configuration files.
config.py file to the
/usr/src/app/instance folder on the container.
This can be achieved by mounting a volume at the appropriate location.
Run the App
With the configuration file in place, you can run the app like so:
$ docker run -d --env-file .env -p 127.0.0.1:5000:5000 tbrlpld/log100days
To document this command and simplify how to start the app, you can use a
Just like the
docker-compose.yml file here in this repo.
This simplifies the start up command to the following, when you are in the working directory of the
$ docker-compose up -d
To stop the service, run the following in the directory with the
$ docker-compose stop
docker-compose.yml file in this repo makes the container only available from the host.
This is, because I think this is a good security practice.
If you do not define the host do be only localhost, then Docker will adjust your IP tables and let outside traffic through to the container.
To achieve outside access to the app while running it only for the localhost, you can use a reverse proxy like NGINX.
An example site NGINX config is in the repo.
This file only needs to be copied/linked to
/etc/nginx/sites-enabled to enable a basic proxy forwarding from a running NGINX instance to the locally available container.
Configure and Run the App in Development
This app utilizes Docker containers for development and deployment.
During development you are going to want to update the source code often and see the changes on the page. To achieve this with a containerized app, you want to override the source directory in the container with the one on your machine (the docker host).
$ docker run -v /Users/tibor/1-Projects/log100days:/usr/src/app -p 127.0.0.1:5000:5000 tbrlpld/log100days:latest
In the above example, the app directory in the container (
/usr/src/app) is overridden by mounting the source directory on the host (e.g.
/Users/tibor/1-Projects/log100days) to its location.
Now you can change the source code locally and the the changes are immediately available in the container.
You might not see the changes populate through to the app in the browser. This is because, by default, the container is running the production server. The production loads the app once on start up. Further changes do no go through.
To see the changes during without having the stop and start the server, or container, you can run the development server.
The development server in the container can be started with the
--entrypoint command line flag.
$ docker run --entrypoint quart -v /Users/tibor/1-Projects/log100days:/usr/src/app -p 127.0.0.1:5000:5000 tbrlpld/log100days run -h 0 -p 5000
Note that the executable (
quart) and the arguments (in this case
run) are not written directly after one another.
Be sure to also configure the
quart development server to accept connections from other hosts than localhost.
Only accepting connections from localhost would mean only accepting from inside the container.
quart development server also requires the environment variables
QUART_DEBUG to be present.
For this app and development, set
These environment variables can be added to the environment file
.env used for configuration of the app (see the Configuration section for more information).
--env-flag to pass the environment variables from the environment file to the container.
$ docker run --entrypoint quart --env-file .env -v /Users/tibor/1-Projects/log100days:/usr/src/app -p 127.0.0.1:5000:5000 tbrlpld/log100days run -h 0 -p 5000
Since this is quite the line, you might want to save this somehow.
This is where
docker-compose comes in.
There already is a
docker-compose.yml file in the repo for production use.
But you can go ahead an create your own file with settings for local development.
docker-compose document for the syntax and available options.
You can run
docker-compose with a different file than the default (
docker-compose.yml) by using the
$ docker-compose -f docker-compose-dev.yml up
Build and Distribute
Run the following command to build the latest image version using the production settings.
$ docker-compose build ... Successfully tagged tbrlpld/log100days:latest
Then tag this image with a version. Make sure this is a new unused version number.
$ docker tag tbrlpld/log100days:latest tbrlpld/log100days:0.1
Push all the latest build images to DockerHub.
$ docker push tbrlpld/log100days
Builds can also be automated on DockerHub by following a certain branch on GitHub.