skip to content
barorin&

Docker実践ガイド|削除コマンド・Dockerfile作成・Composeで環境構築

/ 10 min read

Table of Contents

はじめに

Dockerについて個別に書いてきたメモを、1本の実践ガイドにまとめ直しました。

削除まわりのコマンド、Dockerfileを作るときの進め方、Composeの停止コマンドの違い、そして実際に組んだ環境例が2つという構成です。

インストール手順は別記事にまとめてあるので、そちらを参照してください。

イメージとコンテナを削除する

コンテナを削除する

コンテナは停止してからでないと削除できません。まず状態を確認します。

Terminal window
# 稼働中のコンテナを確認する
$ docker ps
# 稼働中なら停止する
$ docker stop コンテナID
# 停止中のものも含めて確認する
$ docker ps -a
# 停止を確認してから削除する
$ docker rm コンテナID

イメージを削除する

イメージを消すには、先にそのイメージを使っているコンテナを消しておく必要があります。

Terminal window
# イメージを確認してIDを調べる
$ docker images
# イメージを削除
$ docker rmi イメージID

まとめて片付ける

1つずつ消すのが面倒なときは prune 系が早いです。

Terminal window
# 停止中のコンテナを全削除
$ docker container prune
# 使われていないイメージを削除
$ docker image prune
# 停止中コンテナ・未使用ネットワーク・danglingイメージ・buildキャッシュを一括削除
$ docker system prune -a

docker system prune -a はディスクがすぐ空きますが、消える範囲が広いので、残したいイメージがないか確認してから実行してください。

Dockerfileはトライ&エラーで作る

Dockerfileを1行書くたびに docker build していると、待ち時間ばかりで進みません。

先に対話モードでコンテナに入り、動くコマンドを確定させてからDockerfileに書き写すほうが速いです。

Terminal window
$ docker run -it ubuntu:18.04 /bin/bash

この中で apt install ... などを実際に叩いて、通ったものだけを RUN に落としていきます。ビルドを待つ回数が激減します。

docker compose stop と down の違い

コマンド 挙動
docker compose stop コンテナを停止する。削除はしない
docker compose down コンテナとネットワークを削除する

stop したものは docker compose start で再開できます。down した場合は up からやり直しです。

down のオプションもあわせて覚えておくと便利です。

Terminal window
--rmi all # 全イメージの削除
--volumes # volumesに記載したvolumeを削除
--remove-orphans # compose.ymlで定義していないコンテナも削除

起動側のオプションはこの2つをよく使います。

Terminal window
-d # バックグラウンドで実行(同じターミナルを使い続けられる)
--no-recreate # コンテナがすでに存在していれば再生成しない

環境構築例1:Go言語

軽量なalpineベースでGoの環境を作ります。

Dockerfile

FROM golang:alpine
RUN apk add --update && apk add git
RUN mkdir /go/src
WORKDIR /go/src
ADD . /go/src

compose.yml

services:
goapp:
build: .
tty: true
volumes:
- ./go/src:/go/src # ホストのフォルダパス:コンテナのフォルダパス

tty: true を入れておかないと、何もしないコンテナはすぐ終了してしまいます。

起動と実行

Terminal window
$ docker compose up -d --build
# docker compose exec サービス名 コマンド
$ docker compose exec goapp go run hello.go
# コンテナに入ってから実行する場合
$ docker compose exec goapp /bin/sh
>>> go run hello.go

参考:dockerでgo開発環境構築

環境構築例2:FastAPI + PostgreSQL + pgAdmin

API・DB・管理画面の3つをまとめて立ち上げる構成です。

フォルダ構成

Terminal window
fastapi-dev
├── compose.yml
└── fastapi
├── app
│ ├── database.py
│ ├── main.py
│ └── models.py
├── Dockerfile
└── requirements.txt

compose.yml

services:
fastapi:
build:
context: ./fastapi
volumes:
- ./fastapi/app/:/app/
container_name: fastapi
command: uvicorn main:app --reload --workers 1 --host 0.0.0.0 --port 8000
ports:
- 8000:8000
environment:
- DATABASE_URI=postgresql://postgres:postgres@postgres/postgres_db
depends_on:
- postgres
restart: always
postgres:
image: postgres:alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
container_name: postgres
ports:
- 5432:5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=postgres_db
hostname: postgres
restart: always
pgadmin4:
image: dpage/pgadmin4:latest
volumes:
- pgadmin4_data:/var/lib/pgadmin
container_name: pgadmin4
ports:
- 8080:80
environment:
PGADMIN_DEFAULT_EMAIL: pgadmin4@test.com
PGADMIN_DEFAULT_PASSWORD: pgadmin4
hostname: pgadmin4
depends_on:
- postgres
restart: always
volumes:
postgres_data:
pgadmin4_data:

接続先のホスト名にコンテナ名(postgres)を書ける点がポイントです。Composeが同じネットワークに入れてくれるので、IPアドレスを気にせず名前で解決できます。

Dockerfile

FROM python:alpine
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
COPY ./requirements.txt /app/requirements.txt
# ビルドに必要なパッケージを入れて、入れ終わったら消す
RUN apk add --no-cache postgresql-libs \
&& apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev \
&& python3 -m pip install -r /app/requirements.txt --no-cache-dir \
&& apk --purge del .build-deps
COPY . /app/

.build-deps にまとめてから最後に消すことで、イメージサイズを抑えられます。

requirements.txt

fastapi
uvicorn
databases[postgresql]
SQLAlchemy
alembic
psycopg2

アプリ側のコード

database.py
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker
# postgresql://{user}:{password}@{host}:{port}/{database}
engine = create_engine(
"postgresql://postgres:postgres@postgres:5432/postgres_db", echo=True
)
Base = declarative_base()
SessionLocal = sessionmaker(bind=engine)
models.py
from sqlalchemy import Boolean, Column, DateTime, Integer, String, Text
from database import Base
class Item(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(255), nullable=False, unique=True)
description = Column(Text)
date = Column(DateTime)
on_offer = Column(Boolean, default=False)
main.py
from fastapi import Depends, FastAPI
from sqlalchemy.orm import Session
import models
from database import Base, SessionLocal, engine
app = FastAPI()
Base.metadata.create_all(engine) # テーブル作成
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/items/")
def all_fetch(db: Session = Depends(get_db)):
return db.query(models.Item).all()

実行

Terminal window
$ docker compose up -d --build

ホストのブラウザから http://localhost:8000/docs を開くと、FastAPIの自動生成ドキュメントから動作確認ができます。pgAdminは http://localhost:8080 です。

つまずいたとき

コンテナがリスタートを繰り返す

docker compose up したあと、コンテナが起動と停止を延々と繰り返すことがあります。

原因は、コンテナのメインプロセスがすぐ終了していることです。Dockerはコンテナ内のプロセスが終わるとコンテナを停止するため、restart: always を指定していると、停止するたびに再起動して無限に繰り返します。

常駐するプロセスを持たないコンテナ(動作確認用にシェルだけ動かしたい場合など)では、tty: true を付けると終了しなくなります。

services:
app:
image: ubuntu:24.04
tty: true # 疑似端末を割り当ててプロセスを維持する
# restart: always # 原因調査中は外しておく

alpineでbashが使えない

alpineベースのイメージは軽量な代わりに、bashが入っていません。docker exec でbashを呼ぶと失敗します。

Dockerfileに1行足せば使えるようになります。

RUN apk add --no-cache bash

--no-cache を付けると、パッケージのインデックスを残さないのでイメージが小さく保てます。

追加後は通常どおり入れます。

Terminal window
$ docker exec -it コンテナ名 /bin/bash

おわりに

Dockerは覚えることが多く見えますが、実際に手を動かすときに使うコマンドはかなり限られています。

削除まわりと stop / down の違いさえ押さえておけば、あとは環境ごとにcompose.ymlを書き足していくだけです。

この記事を書いた人

barorinのプロフィール画像

barorinCPA & Engineer

会計とITの二足のわらじで働く公認会計士です。Pythonを中心に、会計・監査の実務で使えるコードや、Ubuntu・Docker等の設定メモなどを書いています。