Basic Docker for Curious Moon

Basic Docker for Curious Moon

A few months ago I stumbled upon the best SQL tutorial I've ever seen. Curious Moon by Rob Conery. I've struggled with SQL in the past because the basics are too simple to be memorable, but queries get too complicated too fast. But the real problem is that the fun part about SQL is the data not the SQL. When you're working with boring data, you're working with boring SQL. Unfortunately every tutorial I've come across until Curious Moon has dealt with data about dogs, or cd's, or some other group of things that appeal to a broad audience, but aren't exactly interesting. It's a smart decision on the part of those making the tutorials, but it just doesn't work for me.

What Makes Curious Moon Different

Instead of the traditional text book style instruction we would expect, Conery teaches PostgresSQL through the eyes of a fictional data science intern at an aerospace startup. Cool in its own right to teach something in novel like form, but the most exciting part is that the data used in the story is real Nasa data, taken straight from public records of the Cassini mission.

Also, Curious Moon won't hold your hand. It's designed for you to engage in the narrative and follow along with the main character, Dee. You'll be thrown right into the thick of it, as if you were at the startup yourself. So if Dee is off researching lookup tables, you should too!

If this sounds interesting, but you want to hear a little bit more about the book before purchasing it, listen to Conery on .Net Rocks for a great introduction to the book.

Why Docker

If you're using a Windows PC like I am, Conery recommends using a virtual machine or a hosted service for Postgres. That way, you can follow along with the bash commands and unix flavored programs used in the book. But neither a VM nor a hosted service was an option for me. I needed something similar to a virtual machine, but simpler and with no threat of a bill in the mail.

This is where docker comes in. Docker makes it easy to create operating system level virtualizations called containers. Containers allow us to isolate our applications and dependencies from the rest of our system. On the surface they're similar to virtual machines but lighter weight and with less functionality (though I'm sure that is debatable).

If you're using Windows, and have Windows 10 Professional Edition (or something better) you can use Docker for Windows. Otherwise, you'll need Docker Toolbox (for Windows).

We'll use one long command in the docker terminal to create our Postgres image and run the container.

docker run --name curious-moon -v ~/curious-moon/c-moon-vol:/c-moon-vol -e POSTGRES_PASSWORD=mysecretpassword -d -p 5432:5432 postgres

Lets break this down.

docker run <image-name>:<tag-name> is our base command. If you don't specify a tag-name docker will automatically pull and run the image with the 'latest' tag. postgres is our image-name, and we're fine with the latest postgres image.

--name <container-name> lets you set the name of the container. If you don't set one manually, docker will assign the container a random name. Here, we've set our container name to curious-moon.

-v <local-directory>:<container-directory> will create a volume. A volume lets us share files between our local environment and the container. Any files created in either directory will be accessible from the other. Without a volume, there is no way to share files between systems. We could use the docker cp copy command to copy files from our system to the container, but it's much easier to create a volume for sharing files.

-e <variable>=<value> lets you set an environment variable. We want to use an environment variable for our password, so we use -e followed by our variable POSTGRES_PASSWORD and set it equal to our password mysecretpassword.

-d sets the container to run in background mode. Running the container in background mode allows us to continue to use the cli. In foreground mode, the cli is for logging only

-p <local-port>:<container-port> binds a port on a local machine to a port on the container. The -p stands for "publish ports". The first port listed is our local port. The second is the container port. 5432 is the default port for Postgres, so we'll use and bind it to the same port on our machine. I haven't actually needed this for Curious Moon yet, but it comes in handy if you want to hook up a local program to the database.

At some point we might want to stop the container. To stop a container, docker stop <your-container-name> is the command we want. To start it up again, we'll use docker start <your-container-name>.

If we want to see a list of your containers, the docker ps command lets us see our running containers. The docker ps -a command lets us see both our running and stopped containers.

If we get our docker run command wrong, we can delete the container using the docker rm <container-name> command.

Using a Bash Shell in the Container

To interact with our container we'll need a way to execute commands in the container itself.

docker exec <container-name> <command> allows us to run commands against the running container. We'll use docker exec to attach a shell to the docker container so that we can browse it, and to interact with the Postgres database itself.

Here is the command we need to create a bash shell in our container:

docker exec -it -u postgres curious-moon /bin/bash

-it or -i interactive, and -t tty, creates a text IO environment and keeps it open for us.

-u sets the username for executing commands. Our default user is not the "postgres" user, so we will set our username to postgres when we execute psql commands.

curious-moon is our container, and /bin/bash is the command for a bash shell.

Now we can use normal unix commands and can even install new programs and packages in our container. For example, you may need to add make to your container. You can do so using the familiar command apt-get install make. Keep in mind that you'll need to use the root user, not the postgres user, if you're installing updates and programs.

That's all Folks

This set of commands should give you everything you need to get started using docker for Curious Moon. Keep in mind this is only scratching the surface of Docker. Next steps might be to look into Dockerfiles, Docker Compose, and using Docker containers for your own projects and programs.

Reference: Curious Moon by Rob Conery, Rob Conery, Conery on .Net Rocks, Docker run, Docker exec, Containers, Postgres image, Docker for Windows, Docker Toolbox (for Windows).