Introduction & Project Setup
Hello everyone. Today I thought we'd take a look at adding Postgres into the Rails 7.1 Docker config. So with 7.1, the plan is to include a Docker file and I thought it'd be cool to take a look at Docker Compose as an option to also throw Postgres in here so you don't have to do a lot of thinking when you do the setup.
So to get started, let's go ahead and let's create a new Rails app. We're going to say rails new, I'm going to call this one video, I'm going to pass in the --main flag so that it pulls it from the main branch, and then I'm going to do a --database=postgresql just like that, and then we can go ahead and run that.
Now while that's running, we can sort of talk about what we are going to be implementing here, because it's largely going to be just a basic Docker file. If you're not familiar, we in the previous video talked about how 7.1 ships with a Docker file. The benefit of this is we can use that Docker file to create an image, which allows us to specify that we should use that image inside of a Docker Compose file. So CD into our video project here, we can go ahead and open this up in VS Code, and we can take a look at what I'm elaborating on about.
Configuring the Dockerfile for PostgreSQL
So to do this, we're going to come over here and we're going to get started inside of the actual Docker file itself. So this is shipped by default now, and there's really nothing in here that we have to consider changing except for the build dependencies. We do need to pretty much overhaul. Reason being, this does not update if you change your database adapters.
So we're going to do is we're going to place this build-essential and the libvips, we're going to keep those. But then right after that, we're going to add in a bash, a bash-completion, libffi-dev, tzdata, postgres, node.js, npm, and yarn. And then we can go ahead and save that.
Now I think for the rest of this, we're probably good to go. And we can probably save this. It will expose Port 3000 right here, that's good.
Modifying the Docker Entrypoint Script
Next, we're going to come into our bin and our, I think it's Docker entry file. And in the Docker entry file, what we want to do real quick is just make sure that when we pass in the bin/rails command, which we're going to be passing in, of course, to run our server, we want to make sure that we are also running the db:create command so that our Postgres database gets created. So we just go ahead and we save that, and then we're good to go.
Creating the Docker Compose File: DB Service
The next thing we want to do after we do that is come into our, I guess, VS Code, right-click, new file, and create a docker-compose.yaml. This is going to look very similar to the Docker file that we were using. The difference here is we start with a version three, then we have a Services block, and then we have a DB block. I'm going to be doing quite a bit of copying and pasting here just because, I mean, it's it's it's pretty simple.
You just create the block as specified. A lot of this stuff you can find online if you look for like a Postgres, you know, image. You'll just find something similar to this where they sort of like bake it out for you so that you don't have to do a lot of thinking. So it does create a volume for us, it grabs the image from online, it gives it a container name, and it gives it a command that it needs to run. We also need to make sure that we're tabbing this over because YAML will yell at us if we don't have the appropriate indentation.
I'll have this entire project in a repository linked in the video description. We're then going to give it an environment where we pass in the Postgres database, user, and password. Make sure you copy these down. This way you can, of course, rename these if you so desire, but we're going to be referencing them in a couple of places where we don't really get syntax help. So you're going to want to make sure that you're being very consistent with what you name these.
Okay, so this is our Postgres block right here. To create the environment variables, we just come down here, right-click, new file, .env. And as soon as you create this .env, you're also going to want to add this to your gitignore, just to make sure that you aren't pushing this up. Now in my case, I'm going to do a bad practice and I'm going to leave it off of here. And ultimately you can do either, it's just going to require you to copy and paste later. In my case, I'm not going to do that because it's fine if the world sees these environment variables. So the next thing I want to do is come into our next block. This is going to be for our actual Rails app.
Configuring the Rails App Service and .env
And the first thing we want to do is build this application. Now in the DHH post or the commit, you can see right here he has the -t and then he calls app and .. We don't need to do that. We're just building the directory we're in, just like that. Next step is going to be to do a, and I have to get rid of some code here because that's a spoiler for the next video, command where we just run the ./bin/rails server, which we of course want to match up with the command we're expecting to see in the Docker entry. So if you change one, you're going to want to make sure you change the other, which might explain one of the errors I was running into, which is fantastic, because I was getting a little bit salty about that.
Next, we're going to have to pass in some environment variables and these probably aren't all necessary, but I'm just going to go through the list. First one, we want to specify the environment we're running in, which is going to be production. So at this point, I'm going to go ahead and open up the .env file and we can start adding these. So we want a production environment. We want to specify the Postgres host, which is going to be DB, which we're making sure matches the host service we have right here. That's the only reason we're using it.
We're then going to have the database itself that we want to use, which in my case is called demo_db_production, but we can of course change that to video_db_production. I then gave it a user with the username of Dean and a password of password123. I originally had these as user and password, but I didn't want to make this too confusing. We then give it a master key which we get from our... this is interesting. I'm going to keep this here because I'm a little bit concerned that it just read the encrypted key. We get this from our config and our master.key. And it looks like it didn't read it, so that's good. Let's go ahead and paste that in there.
Next, in my case, I had some additional variables here that we probably don't need for this one yet, so I'm going to go ahead and skip those two, skip that one. And I think we're good with these, actually. The next thing I want to do is come over to our config and our database.yaml.
Updating the Database Configuration File
Now in here, what I'm going to do is get rid of all of these comments just so it's a bit easier to see all the changes I make here. This part should be pretty quick.
Ahead and do this. And now what we want to do inside of our database.yaml file is we want to reference all of those neat little environment variables we made. So up here in our default adapter, we're going to say this is the host and we pass in the environment, which is POSTGRES_HOST. We want to give it the port, just to make sure we're being thorough. Go ahead and do that. Then we can do something for the username and the password.
And then we're going to want to make sure we do that for everything. Now, of course, in an Ideal World, you wouldn't use the same username and password for your development, test, and production. Your production would probably be a different one. But then down here for production, what we can do is we have our database, username, and password. We're just going to replace those with our POSTGRES_USER and password just like that. So again, you have a couple different configuration options here. If you want to change these, you can also set these to environment variables. But at this point, we now have our database hopefully set up, so we can come back over to our docker-compose file.
Finalizing the Docker Compose File
And inside of our docker-compose file, hopefully we can finish this up. So after the environment variables here, which I need to still set. So what we're going to do for those is we're going to grab the entire list of them. So the next thing is going to be the host. Hopefully this works, it does not. I'm going to tab these over after we're done. Then it's going to be the POSTGRES_DB, which for some reason worked fine. The POSTGRES_USER, the POSTGRES_PASSWORD, sorry, password like that. And then we need the RAILS_MASTER_KEY. And then I'll go ahead and tab this back over like that.
Next step is going to be to do the volumes, which will just hop in right there. And then we need to say this has a app storage volume, which we need to also tab over. And then the last step is going to be to say that this depends on the database just like that.
Okay, and now that we have all that, we just come down here and we just say we have a volumes block. And I need to mute my computer because I'm getting some noises from one of the tabs or something, I don't know. And then after we declare the volume blocks, we then say this also has a network which is just going to be called demo default. Although now that I'm looking at this, that might not be necessary, we'll see. So let me come through here and make sure all this is indented properly. It looks like all of these need to go back one step so that we only have one level of indentation. Or it looks fine. I think this is okay. Let's just go ahead and let's try to run this and see what happens. Worst case scenario, everything blows up, which is always a fun time.
Building, Running, and Testing the Application
Okay, so to run this, what we can do is we can start by running a docker-compose and then build. That will run a Docker Compose out of this directory. I'll hit F11 so we can look at the pretty little stuff scrolling through. Okay, so now we can go ahead and give this a try. We had our Docker build command. The next thing we can do is a docker-compose up, I think.
Okay, that was my fault. We did need to include a ports block right here. And as soon as we have this ports block, we should hopefully get sent to the Rails application. Now, it'll tell us this page doesn't exist yet, so let's just go ahead and make it exist. We'll stop this server, do a rails g scaffold Post with a title and a body of type text, and then we can run that. And then let's go ahead and let's come into our routes.rb and here we can just say route to the posts controller, index action.
After we do that, we can then do a docker-compose and a docker, or a docker-compose build and a docker-compose up, which will hopefully run all of this. You'll see we skip a lot of the steps except for where we added that migration. And then right here, it runs the migration, you can hopefully see that real quick. And now if we come over here to localhost Port 3000, we can create a post. We can create it, we can hit back. We can stop our server, we can start our server, and you'll see that that persists.
Because in our Docker Compose file right here, and this actually ran pretty quick so we can refresh already, we declared that Postgres data as a mounted volume. So that exists on our hard drive, which we can see over here in our Docker volumes. Right here I have the video Postgres data. So yeah, that's how you can have Postgres running with Docker and 7.1 of Rails. It's pretty, pretty easy now.
Summary and Key Takeaways
I know what you're thinking, this is a lot to remember. But don't worry, you just copy this file, you come into your Dockerfile and you change the install dependencies. You then come into your database, which is in your config, your database.yaml, and you add in your environment variables. And then you come into your .env and you add in your environment variables in here. Your master key, you just get that from your config/master.key, and it is that easy to get this up and running.
And you can, of course, push this to like DigitalOcean, it'll work just fine. But yeah, that's going to do it for this video. Hopefully this was helpful and hopefully I will see you in the next.