+++ date = 2024-04-08 title = "Using Docker Desktop to Create a Development Web Server" description = "" draft = false +++ When developing websites locally, I often use a simple Python web server to observe the changes. ```sh python3 -m http.server ``` However, this approach has its limitations. For example, this approach does not enable logging or access controls. You also need to customize `SimpleHTTPServer` if you have advanced needs from your web server. So, I went to find an alternative that is almost as easy and far more extensible and found Docker Desktop to be a suitable replacement. # Docker Desktop ## Installation [Docker Desktop](https://www.docker.com/products/docker-desktop/) is a desktop GUI for the phenomenal Docker container software. This allows you to manage containers, images, volumes, environments, and extensions via an easy-to-use GUI. To install, open the link above and click the `Download` button for your platform. I'm going through this process on an M2 Macbook, so I downloaded the Mac - Apple Chip version. Open the installer and follow the installation process until the application finishes the installation process. ![Docker Desktop on macOS](https://img.cleberg.net/blog/20240408-docker-local-web-server/docker-desktop.png) ## Creating an Nginx Container I prefer to use the command line to create containers, so the following commands will be input via the terminal. The following command will create a container, using the `nginx` image: 1. `-d`: Run this container as a daemon (detach) 2. `-p`: Allocate a port in the format `:` 3. `-i`: Keep STDIN open even if not attached 4. `-t`: Allocate a pseudo-TTY 5. `-p`: Allocate a port in the format `:` 6. `--rm`: Remove the container once it's done running ```sh docker run -it --rm -d -p 8000:80 --name web nginx ``` You can navigate to to see the resulting page. ![Default Nginx Container](https://img.cleberg.net/blog/20240408-docker-local-web-server/default-container.png) ## Customizing the Nginx Container Now that I have a container running the Nginx web server, I need to link some volumes so that I can modify the site configuration and provide the web files to serve. Let's start with the new command, which adds two volumes: 1. `:/usr/share/nginx/html`: This is the directory where you will provide the web pages for the server to serve. 2. `:/etc/nginx/conf.d/default.conf`: This is the Nginx configuration file for your site. To see the updates, you can delete the previous container in the GUI or run `docker stop web` to stop the container. Once stopped, you can run the new `docker run` command below. ```sh docker run -it -d -p 8000:80 --name web -v ~/Source/cleberg.net/.build:/usr/share/nginx/html -v ~/Source/cleberg.net/nginx-config.conf:/etc/nginx/conf.d/default.conf nginx ``` Here's an example of my development configuration file. ```conf # nginx-config.conf server { server_name cleberg.net www.cleberg.net; root /usr/share/nginx/html; index index.html; autoindex on; access_log /var/log/nginx/cleberg.net.access.log; error_log /var/log/nginx/cleberg.net.error.log; location / { try_files $uri $uri/ =404; } listen [::]:80; listen 80; } ``` ![](https://img.cleberg.net/blog/20240408-docker-local-web-server/custom-container.png) # Customizing Deployment Actions I am currently blogging with [weblorg](https://emacs.love/weblorg/), which uses a custom `publish.el` file to build the static site. Within this file, I have configured my deployment process to check for the `ENV` variable in thesh and if it's set to `prod`, the script will set the base URLs to `https://cleberg.net`. If not, it sets the base URLs to `localhost:8000` (which matches the port used in the container above). Therefore, I have modified my `build.sh` script to build with `localhost` URLs if `ENV` is not set to `prod`. It also prevents the build process from sending the built files to the production web server. ```sh #!/bin/bash if [ "$ENV" == "prod" ]; then echo "Environment = Production" && \ rm -rf .build/* && \ emacs --script publish.el && \ scp -r .build/* ubuntu:/var/www/cleberg.net/ else echo "Environment = Development" && \ rm -rf .build/* && \ emacs --script publish.el fi ``` You can modify the container in numerous ways and this approach allows you to create complex scenarios for your web development purposes. I highly recommend switching over to a container-based approach for simple, local web development.