You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The app (for right now) isn't using containers. You'll make this change as your first task.
3
+
The Memes-R-Us website uses a PostgreSQL database to store the available memes. Therefore, to run the app in development, you will need a local database.
4
4
5
-
The Memes-R-Us website is fairly simple. It is a Node app with a PostgreSQL database.
5
+
But, it's often not enough to have only a database, as you need a user to connect with, schemas, and initial data.
3. Write and share schema files to auto-populate the database
12
12
13
+
By the end of this section, you will have a working application!
13
14
14
-
## Starting the app
15
+
16
+
> [!IMPORTANT]
17
+
> Getting started with containers can be daunting. For many developers, the easiest approach is to
18
+
> start with the services their app depends on (databases, caches, etc.).
19
+
>
20
+
> Later, if they decide to run the app itself in a container during development, they can certainly do so.
21
+
22
+
23
+
24
+
## ▶️ Starting the app
15
25
16
26
If you haven't done so, open the VS Code environment in the panel on the right.
17
27
18
28
> [!NOTE]
19
-
> All commands in this Labspace must be run in a terminal in Labspace-provided VS Code editor.
29
+
> All commands in this Labspace must run inside a terminal within the Labspace-provided VS Code editor.
30
+
>
31
+
> For convenience, you can press the Play button to run the command.
20
32
21
33
1. Install the Node dependencies by running the following command:
22
34
@@ -32,9 +44,7 @@ If you haven't done so, open the VS Code environment in the panel on the right.
32
44
33
45
This will start the app using `nodemon`, which will automatically restart the app when changes are made.
34
46
35
-
3. Open your browser to http://localhost:3000 to see if the app launched.
36
-
37
-
Instead of the app, you should see the following error:
47
+
3. Open your browser to http://localhost:3000. Instead of the app, you should see the following error:
38
48
39
49
```plaintext no-copy-button
40
50
Error: connect ECONNREFUSED 127.0.0.1:5432
@@ -44,12 +54,16 @@ If you haven't done so, open the VS Code environment in the panel on the right.
44
54
at async /home/coder/project/src/index.js:17:22
45
55
```
46
56
47
-
This is because the app is trying to connect to a postgres database, but it isn't up and running yet.
57
+
This error occurs because the app is trying to connect to the postgres database, which isn't running yet.
58
+
59
+
Let's fix that!
48
60
49
61
50
-
## ▶️ Starting PostgreSQL
62
+
## ▶️ Starting a PostgreSQL container
51
63
52
-
Containers make it incredibly wasy to run a PostgreSQL database. Let's see how easy!
64
+
Containers allow you to simply run PostgreSQL. No installation required!
65
+
66
+
In order to run a container, you need a container image. Fortunately, there is an [official postgres](https://hub.docker.com/_/postgres) image.
53
67
54
68
1. Use the `docker run`commandin a terminal to start a PostgreSQL container:
55
69
@@ -67,7 +81,7 @@ Containers make it incredibly wasy to run a PostgreSQL database. Let's see how e
67
81
68
82
The output that you see is the full container ID.
69
83
70
-
2. To view the running containers, you use the `docker ps` command:
84
+
2. To see a list of running containers, use the `docker ps` command:
71
85
72
86
```console
73
87
docker ps
@@ -83,29 +97,13 @@ Containers make it incredibly wasy to run a PostgreSQL database. Let's see how e
83
97
Hooray! It's running!
84
98
85
99
> [!IMPORTANT]
86
-
> This single command helps illustrate the power of a container. Containers make running apps easy. **No installs. No setup. Just run.**
87
-
88
-
3. Connect to the database using the `psql` tool:
89
-
90
-
```bash
91
-
psql -h localhost -U postgres
92
-
```
93
-
94
-
When you're prompted for the password, enter the password we defined in the command:
100
+
> To emphasize, this single `docker run`command helps illustrate the power of a container. Containers make running things easy. **No installs. No setup. Just run.**
95
101
96
-
```bash
97
-
secret
98
-
```
99
-
100
-
You should now be connected! It worked! 🎉
102
+
## 📞 Connect the app to the database
101
103
102
-
5. Disconnect from the database by running the following command from inside the `psql` tool:
103
-
104
-
```bash
105
-
\q
106
-
```
104
+
Now that the container is up and running, it's time to update the app to connect to it.
107
105
108
-
6. To configure the app to connect to the database, create a `.env` file with the following content:
106
+
1. The app uses a `.env` file to configure the database settings. Create a `.env` file with the following content:
109
107
110
108
```dotenv save-as=.env
111
109
PGHOST=localhost
@@ -114,8 +112,10 @@ Containers make it incredibly wasy to run a PostgreSQL database. Let's see how e
114
112
PGPASSWORD=secret
115
113
PGDATABASE=postgres
116
114
```
115
+
116
+
This will tell the app to connect to `localhost:5432` (remember, we're exposing the container's port) and using the default username with the password we supplied.
117
117
118
-
7. With the database running and the app configured, the app should work, right? But, opening the site now gives us another error:
118
+
2. With the database running and the app configured, the app should work, right? But, opening [the site](http://localhost:3000) now gives another error:
119
119
120
120
```plaintext
121
121
error: relation "memes" does not exist
@@ -130,9 +130,9 @@ Containers make it incredibly wasy to run a PostgreSQL database. Let's see how e
130
130
131
131
## ➕ Populating the database
132
132
133
-
Docker's database container images provide the ability to load "seed" files into the container, making it easy to create tables and provide data at startup.
133
+
Docker's database container images provide the ability to load "seed" files into the container during first launch, making it easy to create tables and provide data at startup.
134
134
135
-
In the following steps, you are going to create the schema files and then update the database to run them at startup.
135
+
In the following steps, you are going to create the schema files and provide them to the database container using a feature called [bind mounts](https://docs.docker.com/engine/storage/bind-mounts/).
136
136
137
137
1. In the project, create a folder named `db`. You can either do so using the IDE directly or by running the following command:
138
138
@@ -150,7 +150,7 @@ In the following steps, you are going to create the schema files and then update
150
150
);
151
151
```
152
152
153
-
This will create a simple table named `memes`that will have three columns - the ID of the meme, its URL, and a timestamp for when it was created.
153
+
This will create a table named `memes`with three columns - the ID of the meme, its URL, and a creation timestamp.
154
154
155
155
3. In the `db` folder, create a file named `02-initial-data.sql` with the following contents:
156
156
@@ -161,17 +161,17 @@ In the following steps, you are going to create the schema files and then update
This will insert three memes into the table, specifying only the URLs. The ID and creation timestamps are automatically generated for us by the database.
164
+
This will insert three memes into the table, specifying only the URLs. The ID and creation timestamps are automatically generated by the database.
165
165
166
-
4. Before updating the database container to use these files, you will need to remove the current database container. Do so with the `docker rm` command:
166
+
4. Bind mounts can't be added to a container after it's been started. Therefore, you'll need to restart the container. First remove the existing container with the `docker rm` command:
167
167
168
168
```bash
169
169
docker rm -f postgres
170
170
```
171
171
172
172
The `-f` flag will stop the database before removing the container.
173
173
174
-
5. Use the following command to share the schema files from your workspace into the container (this is called bindmounting):
174
+
5. Use the following command to share the schema files from your workspace into the container with a bind mount:
175
175
176
176
```bash
177
177
docker run -d --name=postgres \
@@ -181,11 +181,11 @@ In the following steps, you are going to create the schema files and then update
181
181
postgres:17-alpine
182
182
```
183
183
184
-
This command adds the `-v ./db:docker-entrypoint-initdb.d` flag, which tells Docker to share the local`./db` directory into the container at `/docker-entrypoint-initdb.d`.
184
+
This command adds the `-v ./db:docker-entrypoint-initdb.d` flag to specify the bind mount. This causes Docker to share the local `./db` directory into the container at `/docker-entrypoint-initdb.d`.
185
185
186
-
The `/docker-entrypoint-initdb.d` directory is a special directory the container is designed to look at when starting up. If there are files there, it'll automatically import them into the database.
186
+
The `/docker-entrypoint-initdb.d` directory is a special directory the container inspects when starting up. If there are files there, it'll automatically import them into the database.
187
187
188
-
6. To confirm the data exists in the database, use the following `psql` command:
188
+
6. Once the container is running, confirm the data exists in the database, use the following `psql` command:
189
189
190
190
```bash
191
191
psql -h localhost -U postgres -c "SELECT * FROM memes"
@@ -204,67 +204,10 @@ In the following steps, you are going to create the schema files and then update
204
204
205
205
Hooray! The database is populated and ready to go!
206
206
207
-
4. Go back to the app (at http://localhost:3000) and validate it works now!
208
-
209
-
210
-
211
-
## 🐳 Using Compose to make everything easier
212
-
213
-
Hopefully, you're starting to see how Docker makes it easy to run services. No need to install anything. Very simple configuration. It just works!
214
-
215
-
But, if your app starts to have quite a few services, telling team members to run a bunch of `docker run` commands is a lot of work.
207
+
4. Go back to the app (at http://localhost:3000) and validate it works now.
216
208
217
-
That's where Docker Compose comes in! With Compose, you can create a `compose.yaml` that defines everything.
218
209
219
-
1. Before you create the Compose file, remove the running database container:
220
-
221
-
```bash
222
-
docker rm -f postgres
223
-
```
224
-
225
-
2. At the root of the project, create a file named `compose.yaml` with the following contents:
226
-
227
-
```yaml save-as=compose.yaml
228
-
services:
229
-
db:
230
-
image: postgres:17-alpine
231
-
ports:
232
-
- 5432:5432
233
-
volumes:
234
-
- ./db:/docker-entrypoint-initdb.d
235
-
environment:
236
-
POSTGRES_PASSWORD: secret
237
-
```
238
-
239
-
You should probably recognize this has almost all of the same config from the previous `docker run` commands, but just in a different format.
240
-
241
-
3. Start the app now by using `docker compose`:
242
-
243
-
```bash
244
-
docker compose up -d
245
-
```
246
-
247
-
The `-d` will run everything in the background. But, you should see output indicating the containers have started:
248
-
249
-
```plaintext no-copy-button
250
-
[+] Running 2/2
251
-
✔ Network project_default Created 0.0s
252
-
✔ Container project-db-1 Started 0.2s
253
-
```
254
-
255
-
4. To prove it's working, run the following commands to delete all of the memes in the database and then add a new one:
256
-
257
-
```bash
258
-
psql -h localhost -U postgres -c "DELETE FROM memes"
259
-
```
260
-
261
-
And add another one into the database:
262
-
263
-
```bash
264
-
psql -h localhost -U postgres -c "INSERT INTO memes (url) VALUES ('https://media.giphy.com/media/l0MYt5jPR6QX5pnqM/giphy.gif')"
265
-
```
266
210
267
-
5. Refresh the browser several times and you should only see a single celebratory meme.
0 commit comments