Fabrefact

a blog by Sara Farquharson

Virtual Party Space Devlog #19: Containerizing an app

Today I finally turned my app into a Docker container, by reverse engineering how the Jitsi Dockerfiles work.

Log

HOW DOES DOCKER-JISI-MEET WORK?

  • project contains a base image built on debian:buster-slim which contains:
    • apt-transport-https apt-utils ca-certificates gnupg wget
    • s6 for process management (via an “overlay”) https://github.com/just-containers/s6-overlay
    • Jitsi’s GPG keys (what for?)
    • frep templating tool https://github.com/subchen/frep
    • a couple wrapper commands apt-dpkg-wrap, apt-cleanup, and tpl to be used in the other dockerfiles
    • if built using the unstable release, also installs jq procps curl vim iputils-ping net-tools
  • base image sets apt-get sources for debian and jitsi packages (so if want to use custom source, will have to add new)
  • each container image extends base by installing at least one jitsi package and some public packages
    • uses the wrapper commands from base image for installing and cleanup
    • web uses ADD docker command instead of apt-get for acme, maybe not available in apt?
  • each service contains a rootfs folder containing config for the service
    • etc is mostly process running directions for s6
      • cont-init.d contains bash script to run when the container initializes
      • services.d contains run commands for processes that run in this service
    • defaults is templates for things like nginx configs, including environment variables
      • these templates are expanded into the mapped /config directory using the tpl wrapper command around frep
  • upon container start, s6 runs 10-config init script, which contains tpl commands to recreate /config files from /defaults
  • web container runs nginx and a cron that runs Lets Encrypt regularly

more about whether to use volumes or not

  • “By default all files created inside a container are stored on a writable container layer” https://docs.docker.com/storage/
    • not persistent when container goes down
    • hard to move to other hosts
    • storage driver reduces performance
  • for the most part, contents of volumes are just config files that are written every time the container starts
    • probably no need to use persistent storage, but also no need to copy in files
  • Let’s Encrypt certificates do need to be persisted

trying new, more ECS-friendly setup for docker-jitsi-meet

Bug fixes

The perils of libraries

  • Made some quick progress with dockerizing, but got blocked on Calla not being able to be included in any normal way
    • npm file:.. syntax being outside the Docker context was an issue, as expected
    • internet suggestion to use Dockerfile in parent directory was a nightmare because entire projects directory gets loaded in as context, which is many Gb (still didn’t work)
    • tried including as tar.gz but kept running into issues with the my-rollup dev dependency
      • I think this was actually due to package-lock.json, and might have worked in the end
  • Chosen path: turn Calla into a proper dependency (and by extension, its dependencies kudzu and my-rollup)
    • using Verdaccio as local npm repository
      • (set as my default repository, remember this when working on other projects)
      • had to “log in”, created account and put in password manager
    • look up how to publish packages (npm publish)
    • use npm pack on my-rollup because it’s just a build script I don’t ever want to touch or use
    • publish kudzu to verdaccio
    • publish calla to verdaccio
    • install still fails due to complaining about some typescript syntax, because package contains TS
    • Calla doesn’t use an outDir, so js files are intermingled with ts files
      • edit tsconfig, publish from ./dist folder (remember to actually include folder!)
    • app still can’t find calla, because main was set incorrectly in package.json
    • Calla.js was incorrectly capitalized because I was trying to cheat and reuse the dist directory, which already had calla.js
      • (this is going to be a problem if I accidentally run the build script instead of just tsc)

Additional configuration

  • got all the server stuff in the same docker-compose as my app, just need to get the extra nginx stuff working
    • nginx configs contain environment variables, which need to get replaced with env vars passed in Docker build
    • jitsi containers use frep for env variable replacements, could do that, but requires learning to start a script
    • envsubstr is a linux cli tool for replacing env vars, still requires a bit of scripting
    • nginx alpine image supports envsubstr automatically starting in 1.19 (mainline, not stable)
  • lets encrypt certificates are good for 90 days, so I only need to get one once and store on volume
  • made sure local lib-jitsi-meet got loaded so Calla doesn’t try to download it again
  • struggled with HTTPS for SO LONG and it looks like the problem was just reusing ports that another container was using.
    • copied over more of the jitsi web configs, probably didn’t need to do that
    • changing ports instantly worked

About this series

Back in mid-December I started an ambitious project to create a custom platform for a virtual birthday party in February. I kept notes on my progress, both for personal reference and to turn into a series of blog posts. It quickly became apparent that I did not have time to both do the project and blog about the project. I have retroactively decided to post my raw notes as a dev log.