0

I have a website with very specific JS code associated with a large, unchanging, MySQL database. I want to be able to distribute the website plus database as a single package for others to be able to run locally, so I have been investigating doing this using docker. Note that I'm not using docker for testing the running app: merely for distributing it for others to look at.

By my understanding, docker images that run a populated MySQL database usually load it up from a .sql file after starting the DB. However, for my database contents, this results in an hour-long wait to populate the database, since the .sql dump is many gigabytes, and takes that long to load. Therefore I was thinking of loading the data into the running database once, keeping the db volume (/var/lib/mysql) local to the image, and creating a snapshot of the image using docker commit once the data has been loaded.

However, this approach seems to go against many standard docker recommendations: usually docker commit is frowned upon, and /var/lib/mysql is stored as a separate data-volume, not saved in the image itself. Nevertheless, my use-case seems different, as (a) the data in the database is not intended to change in the future (b) it takes a long time to load from a mysql dump and (c) the large data store (rather than just the js app code) is one of the main things that I actually want to include in the image.

So is my use-case a valid reason to break convention and use docker commit together with saving the MySQL files in the image itself rather than a separate data volume? Or is there an alternative, more standard way of distributing a fully working, fully-populated web app with a large fixed database store?

user2667066
  • 1,867
  • 2
  • 19
  • 30
  • _“usually docker commit is frowned upon”_ The statement lacks substance; do you have anything to back it up? – ashu May 04 '21 at 08:43
  • Suggestion - Can't you use sqlite to hold static data? – ashu May 04 '21 at 08:46
  • Another approach could be to package a database dump in your docker image. You can restore this dump before starting your application. – ashu May 04 '21 at 08:48
  • Thanks for the comments @ashu. Here's a link talking about docker commit being not recommended (point 5) https://developers.redhat.com/blog/2016/02/24/10-things-to-avoid-in-docker-containers/ . Re sqlite - I suspect the access won't be fast enough for our needs. Re db dump in the image - if the dump is in .sql format it will take too long to load into the DB for sensible packaging as a distributed web app (see discussion in the question) – user2667066 May 04 '21 at 09:08

1 Answers1

0

I found out that instead of using docker commit, you can use multi-stage builds. In an early stage of the build, a RUN command can be used to populate the database (e.g. resulting in the DB files being created in /var/lib/mysql). If /var/lib/mysql is a data volume, then as the last stage of the build, the entire /var/lib/mysql directory can be copied to a permanent, non-data volume location, e.g. /var/lib/mysql_permanent, using e.g.

ENV MYSQL_DATA_DIR=/var/lib/mysql_permanent
# copy the DB files from the previous image
COPY --from=create_database "/var/lib/mysql" "${MYSQL_DATA_DIR}"

The final image will then be created with the correct underlying database files baked into the image. The last build stage then needs to run the mysqld process with a mysqld.cnf file specifying datadir=${MYSQL_DATA_DIR}, to access the correct files. This then bypasses the need for docker commit, and does everything in the build stage.

user2667066
  • 1,867
  • 2
  • 19
  • 30