docker
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| docker [May 14, 2026 at 11:38] – external edit 127.0.0.1 | docker [June 13, 2026 at 03:13] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | # Docker | + | # docker |
| ## What is docker? | ## What is docker? | ||
| Line 67: | Line 67: | ||
| ### Containers | ### Containers | ||
| - | Docker containers are particular instances of an image. You run a container with `docker run -it --rm < | + | Docker containers are particular instances of an image. |
| + | |||
| + | You run a container with `docker run`. The two flags you will use most are `-it` (attach an interactive terminal) and `-d` (run detached, in the background). The `--rm` flag from the Practice section deletes the container automatically when it exits; leave it off when you want the container to stick around. | ||
| + | |||
| + | ``` | ||
| + | docker run -it ubuntu: | ||
| + | docker run -d --name myapp nginx # detached, named " | ||
| + | ``` | ||
| + | |||
| + | Containers that are not running still exist on disk until you delete them. `docker ps` shows only running containers; `docker ps -a` shows all of them, including stopped ones. This is a common source of confusion: you exit a container, it disappears from `docker ps`, but it is still there taking up disk space. | ||
| + | |||
| + | ``` | ||
| + | docker ps # running containers | ||
| + | docker ps -a # all containers, including stopped | ||
| + | docker stop myapp # send SIGTERM, wait, then SIGKILL | ||
| + | docker start myapp # restart a stopped container | ||
| + | docker rm myapp # delete a stopped container | ||
| + | docker rm -f myapp # force-delete a running container | ||
| + | ``` | ||
| + | |||
| + | To run a command inside an already-running container: | ||
| + | |||
| + | ``` | ||
| + | docker exec -it myapp bash # open a shell in the running container | ||
| + | docker exec myapp ls / | ||
| + | ``` | ||
| + | |||
| + | To see what a container printed to stdout/ | ||
| + | |||
| + | ``` | ||
| + | docker logs myapp # print all output so far | ||
| + | docker logs -f myapp # follow output in real time (like tail -f) | ||
| + | ``` | ||
| + | |||
| + | The following are some container-related commands you should remember: | ||
| + | |||
| + | - `docker run -it < | ||
| + | - `docker run -d --name < | ||
| + | - `docker ps` - List running containers | ||
| + | - `docker ps -a` - List all containers including stopped ones | ||
| + | - `docker stop < | ||
| + | - `docker start < | ||
| + | - `docker rm < | ||
| + | - `docker exec -it < | ||
| + | - `docker logs < | ||
| + | |||
| + | ### Volumes | ||
| + | By default everything inside a container is ephemeral: it exists only as long as the container exists, and disappears when you `docker rm` the container. Volumes are how you make data persist beyond the lifetime of a container. | ||
| + | |||
| + | The simplest form is a **bind mount**: you map a directory on your host into a directory inside the container. Whatever is written to that path inside the container is actually written to your host filesystem. | ||
| + | |||
| + | ``` | ||
| + | docker run -it --rm -v / | ||
| + | ``` | ||
| + | |||
| + | Now `/data` inside the container is actually `/ | ||
| + | |||
| + | The other form is a **named volume**: Docker manages the storage location for you, and you refer to it by name. | ||
| + | |||
| + | ``` | ||
| + | docker volume create mydata | ||
| + | docker run -it --rm -v mydata:/ | ||
| + | ``` | ||
| + | |||
| + | Named volumes outlive any particular container. You can mount the same named volume into multiple | ||
| + | |||
| + | ``` | ||
| + | docker | ||
| + | docker volume inspect mydata | ||
| + | docker volume rm mydata | ||
| + | ``` | ||
| + | |||
| + | The key commands: | ||
| + | |||
| + | - `docker run -v / | ||
| + | - `docker run -v < | ||
| + | - `docker volume create < | ||
| + | - `docker volume ls` - List named volumes | ||
| + | - `docker volume rm < | ||
| + | |||
| + | ### Dockerfile | ||
| + | So far you have been running images that other people built. A Dockerfile is how you build your own. It is a plain text file that lists the steps to construct an image, starting from a base image and layering changes on top. | ||
| + | |||
| + | ``` | ||
| + | FROM ubuntu: | ||
| + | |||
| + | RUN apt-get update && apt-get install -y gcc make | ||
| + | |||
| + | COPY . /app | ||
| + | WORKDIR /app | ||
| + | |||
| + | RUN make | ||
| + | |||
| + | CMD [" | ||
| + | ``` | ||
| + | |||
| + | Each instruction (`FROM`, `RUN`, `COPY`, ...) adds a layer on top of the previous one. Docker caches layers: if you rebuild and only the last `RUN` changed, Docker reuses all the cached layers up to that point and only re-executes from the change onward. This is why `apt-get update && apt-get install` should always be in one `RUN` instruction — splitting them means the install can run against a stale cached update layer. | ||
| + | |||
| + | You build the image with `docker build`: | ||
| + | |||
| + | ``` | ||
| + | docker build -t myimage: | ||
| + | docker build -t myimage: | ||
| + | ``` | ||
| + | |||
| + | The `.` at the end is the **build context**: the directory Docker sends to the daemon to use in `COPY` instructions. Keep large files out of it (or list them in `.dockerignore`) because the entire build context is transferred on every build. | ||
| + | |||
| + | Common Dockerfile instructions: | ||
| + | |||
| + | - `FROM < | ||
| + | - `RUN < | ||
| + | - `COPY <src> < | ||
| + | - `WORKDIR < | ||
| + | - `ENV < | ||
| + | - `EXPOSE < | ||
| + | - `CMD [" | ||
| + | |||
| + | The following are some build-related commands: | ||
| + | |||
| + | - `docker build -t < | ||
| + | - `docker commit < | ||
| + | - `docker history < | ||
| + | |||
| + | ### docker compose | ||
| + | Real applications rarely run as a single container. A web application might need a container for the app itself, one for the database, and one for a cache. Docker Compose lets you define all of them in a single `docker-compose.yml` file and bring them all up with one command. | ||
| + | |||
| + | ```yaml | ||
| + | # docker-compose.yml | ||
| + | services: | ||
| + | web: | ||
| + | build: . | ||
| + | ports: | ||
| + | - " | ||
| + | depends_on: | ||
| + | - db | ||
| + | db: | ||
| + | image: postgres: | ||
| + | environment: | ||
| + | POSTGRES_PASSWORD: | ||
| + | volumes: | ||
| + | - pgdata:/ | ||
| + | |||
| + | volumes: | ||
| + | pgdata: | ||
| + | ``` | ||
| + | |||
| + | ``` | ||
| + | docker compose up # build images (if needed) and start all containers | ||
| + | docker compose up -d # same, but detached | ||
| + | docker compose down # stop and remove all containers (volumes are kept) | ||
| + | docker compose down -v # also delete volumes | ||
| + | docker compose logs -f # follow logs from all services | ||
| + | docker compose exec web bash # open a shell in the running " | ||
| + | ``` | ||
| + | |||
| + | Compose automatically creates a shared network for all services, so the `web` container can reach the database simply by using the service name `db` as the hostname. Service names in `docker-compose.yml` are the DNS names inside the Compose network. | ||
| + | |||
| + | The key commands: | ||
| + | |||
| + | - `docker compose up` - Start all services defined in `docker-compose.yml` | ||
| + | - `docker compose down` - Stop and remove all services | ||
| + | - `docker compose ps` - Show the status of all services | ||
| + | - `docker compose logs -f` - Follow logs from all services | ||
| + | - `docker compose exec < | ||
| + | - `docker compose build` - Rebuild images without starting containers | ||
docker.1778758708.txt.gz · Last modified: by 127.0.0.1
