How to use run, start and exec subcommands against a container

Overview

  • Start an existing container.
      $ docker start my-app
    
  • Access the container’s system.
      $ docker exec -it my-app bash
    
  • Run a container. Use --rm to delete it.
      $ docker run \
          --rm \
          --name my-app \
          -p 3000:3000 \
          -d \
          --init \
          my-node-img
    

Run in new container

Run a command in a new container. The container will then stop when it is finished, unless it continues to run like for a server.

$ docker run IMAGE
$ docker run IMAGE COMMAND

The container will get a different random name on each run and you’ll end up with a lot of containers unless you use rm to delete it each time.

e.g.

This will do nothing and then exit.

$ docker run python:3.9

Use default entry-point (in this case Python terminal) and use interactive mode.

$ docker run -it --rm python:3.9

Specify shell as entry-point and interactive mode.

$ docker run -it --rm python:3.9 bash

Give the container name if you want. This can be useful if you have long-running container like a server. You’ll want to use the rm flag otherwise you’ll get an error on the 2nd run that the container name already is used.

$ docker run -rm --name CONTAINER_NAME IMAGE

e.g.

$ docker run --rm \
    --name my-app \
    python:3.9

Run in existing

Run a command in an existing and running container, given a tagged name or ID.

  1. Create the container:
     $ docker run IMAGE --name CONTAINER_NAME
    
  2. Start it:
     $ docker start CONTAINER_NAME
    
  3. Execute inside it:
     $ docker exec CONTAINER_NAME
    

That is useful if you want to tunnel in and use an interactive session with Bash, Python, etc.

$ docker exec -it CONTAINER bash

If you container exits immediately when it run, you’ll struggle to exec into it.

So then use run against a built image. Set a new container from a given image, deleting the container when done. Pass a shell entry point.

$ docker run --rm -it \
    IMAGE \
    --entrypoint bash

In VS Code, under the Docker extension and “Images” you can select an image and “Run interactive” to achieve the same thing. Though, you might start with Node or something else, as you can’t specify Bash.

Interactive

Start an interactive Node console in a target image.

e.g.

Node image, with node as default entrypoint.

$ docker run -it node
>

Node image, with bash as custom entrypoint.

$ docker run -it node bash
#

Open ports

Expose and publish ports.

Format:

  • --publish EXTERNAL:INTERNAL

With that flag, that you don’t need EXPOSE in the Dockerfile. Also, using EXPOSE alone doesn’t publish.

Example:

$ docker run --rm -p 80:8080 node-app

The Node app will serve on port 8080 and Docker routes that port 80 on the host.

Network

From Network settings.

--network="bridge" : Connect a container to a network
                      'bridge': create a network stack on the default Docker bridge
                      'none': no networking
                      'container:<name|id>': reuse another container's network stack
                      'host': use the Docker host network stack
                      '<network-name>|<network-id>': connect to a user-defined network

e.g. If my-network was created by Docker Compose and you want to add a container to that network.

$ docker run --network='my-network'

Start shell

Start an interactive Bash shell in the container by setting the entrypoint. This overrides whatever value was set in the Dockerfile for ENTRYPOINT.

$ docker run -it my-app bash

Or with more verbose --entrypoint ENTRYPOINT flag.

Note that flags must come before the app name.

$ docker run -it --entrypoint bash my-app 

Avoid

  • Create - I don’t think I’ve ever had to run create.
      $ docker create --init \
          --name my-app \
          -p 3000:3000 \
          my-node-img
    
  • Attach to a container (not recommended).
      $ docker attach my-app