Learning paths / Containers / Running containers

Running a container: ports and environment

Reading · 6 min · Module 3, lesson 1 of 432 min left in this module

Module 3 · Running containersLesson 1 of 4

Goal: Start a container from an image with a port mapped to your machine and environment variables passed in.

3:33 · captions and chapters · narrated with an AI-generated voice
Transcript

Narration uses an AI-generated voice.

[00:00] Where we're going

By the end of this video, you'll be able to start a container with a port open to your machine, and a setting passed in. It takes one command. And two of its flags do the connecting. One opens a door from your machine into the container. The other hands the app a setting.

[00:18] One command, left to right

Here's the command from the lesson. Let's read it left to right. The first flag runs the container in the background. Then a name, hello API, so later commands can use it instead of an ID. Then the port flag. The lesson uses three thousand on your side. Here it's eighteen nine sixty-one, just a free port on this machine. Then the environment flag, with a setting called GREETING. The image comes last. Every flag has to come before it. Run it, and Docker prints the new container's ID.

[00:55] Ports: your side, then the container's

Inside, the app listens on eighty eighty. And it has no idea your machine exists. The container has its own network. So without the port flag, localhost on your machine doesn't lead to the app at all. The port flag reads host, then container. The right side must match where the app listens: eighty eighty. The left side is any free port on your machine. So two containers can both listen on eighty eighty inside, as long as each one gets its own host port.

[01:28] Prove it

Now prove it. Send a request to your side of the door, on the hello path. The answer comes from inside the container. And look at the message: Hello from a container. That's the setting we passed in.

[01:43] Settings at run time

Path two put configuration outside the code. Containers follow the same rule. The image holds the code. The environment flag gives each run its settings. Neither flag changes the image. So one image runs anywhere, with different doors and settings. This app reads two settings: GREETING, and PORT. So you can move it, too.

[02:08] Move the port

This one is called moved. It sets PORT to nine thousand. Change PORT, and the right side of the port flag changes with it. Nine thousand, in both places. Now ask it for hello. No greeting was set this time, so you get the default: Hello, world.

[02:28] Clean up, and one warning

When you're done, remove both, by name. That frees the names for the Try it lesson. One warning. Anyone who can run Docker commands on that machine can read every variable you passed in, in plain text. And on ComputeSphere, a service's port is the right side: where your app listens. There's no host port to pick.

[02:51] Recap

To recap. The port flag reads host, then container. The right side is where the app listens. The environment flag hands the app its settings, at run time. And every flag goes before the image name.

Here's a question to check yourself. An app in a container listens on port five thousand. You want to open it at localhost, port eight thousand. Which flag? Eight thousand, then five thousand. Your side first, the container's side second. Next, logs, exec and restart behaviour. I'll see you there.

Key idea

docker run starts a container from an image. Two flags connect it to the outside: -p opens a door from a port on your machine to a port inside the container, and -e hands the app a setting. Neither changes the image, so one image runs anywhere with different doors and settings.

The commands here are for reading; no need to run them. You'll run them for real in the Try it lesson, 3.3.3.

One command, read left to right

docker run -d --name hello-api -p 3000:8080 -e GREETING="Hello from a container" quay.io/computesphere/learn-sample-api:1.0.0
  • -d runs it in the background and prints the new container's ID.
  • --name hello-api gives it a name to use in later commands, instead of the ID.
  • -p 3000:8080 maps port 3000 on your machine to port 8080 in the container.
  • -e GREETING=... sets an environment variable inside the container.
  • The last argument is the image. Every flag must come before it.

Anything after the image name is passed to the container as its command, not read as a flag.

Ports: your side, then the container's side

The app inside listens on 8080 and has no idea your machine exists. The container has its own network, so without -p, localhost on your laptop doesn't lead to the app at all.

-p 3000:8080 reads host:container. The right side must match where the app listens; the left side is any free port on your machine. So curl localhost:3000/hello reaches the app:

{"api_key_set":false,"message":"Hello from a container"}

Two containers can both listen on 8080 inside, as long as each gets its own host port.

Environment: settings at run time

Path 2 put configuration outside the code. Containers follow the same rule: the image holds the code, and -e gives each run its settings. This app reads GREETING and PORT, so you can move it too:

docker run -d --name moved -p 3001:9000 -e PORT=9000 quay.io/computesphere/learn-sample-api:1.0.0

Change PORT and the right side of -p changes with it. For more than a few variables, --env-file .env reads them from a file.

Ran these anyway? docker rm -f hello-api moved removes both, so the names are free for 3.3.3.

docker inspect prints every variable a container was started with, in plain text. Anyone who can run Docker commands on that machine can read them.

Check yourself

An app in a container listens on port 5000. You want to open it at localhost:8000. Which flag?
You run docker run quay.io/computesphere/learn-sample-api:1.0.0 -e GREETING=Hi. The greeting is still Hello, world. Why?

In the docs