Docker について備忘録をまとめる
docker コマンドについて
イメージ、コンテナへの操作
docker tag で名前を変更する
build などしてイメージが hash になっているケースで名前をわかりやすくつけたい場面がある。tag を使うしかなさそう?
docker build .
docker tag 09134185310 myapp:latest
docker file からファイルをコピーしてくる
docker create --name temp-image some-image
docker cp temp-image:/some/dir/file.tmp file.tmp
docker rm temp-image
コンテナ実行
docker run = docker create & docker start
run はコンテナを作成して、起動する。このとき、 -d の dettach を行うとそのままプロセスがバックグラウンドで走り続ける。 -i はコンテナから exit したらコンテナを落とす。
privileged を付けるとで何でもできる特権 container になる
docker run --it alpine:latest --privileged
docker exec は実行中の docker process でコマンド実行
docker exec -it <コンテナ名>
で docker で現在実行中のプロセス(ただし、PATH に shell がある)に入ることができる。
docker ps -a で停止しているプロセスも含めてすべて閲覧
sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
71e0cf6a50a6 101779243274 "/bin/bash" 5 weeks ago Exited (137) 2 weeks ago angry_fermat
d5577c8aca3f bbe77145eb18 "/bin/bash" 5 weeks ago Exited (137) 2 weeks ago eager_carson
b8c0b1a734a6 101779243274 "bash" 6 weeks ago Up 8 days interesting_shtern
3ce1af5ce44c bbe77145eb18 "/bin/bash" 8 weeks ago Exited (137) 2 weeks ago hardcore_torvalds
0456af55e878 bbe77145eb18 "/bin/bash" 2 months ago Exited (137) 2 weeks ago lucid_swanson
イメージ、コンテナのクリーンアップ
TAG が none の image 削除
docker image prune
docker 1.25 から利用ができるようだ。それまでは下記のように複数のコマンドを使う必要があった。
docker rmi $(docker images -f "dangling=true" -q)
docker でイメージ削除を for で実施する
arr=("image_id1" "image_id2" "image_id3"); for i in "${arr[@]}" ; do sudo docker rmi -f $i ; done
docker で exit して止まっているコンテナの削除を行う
docker rm $(docker ps -aq)
で止まっているコンテナの削除ができる。
$(docker ps -aq)
は running のものも対象になっているが、 docker rm は running のコンテナは削除しない。
docker run を抜け出したら、コンテナを落とすようにする
docker run --rm -it --name="default" alpine /bin/sh
--rm
をつけることで、コマンドから抜け出したらコンテナは落ちるようにできる。
これで、色々と試行錯誤して、docker commit や save を行えば、DockerImageができるので、あとは消すだけで良い。
ヘルプで出てくる中のよく使うコマンド
# 個人的に普段あまりつかわないサブコマンドをコメントアウトする
$ docker -h
Common Commands:
run Create and run a new container from an image
exec Execute a command in a running container
ps List containers
build Build an image from a Dockerfile
pull Download an image from a registry
# push Upload an image to a registry
images List images
# login Log in to a registry
# logout Log out from a registry
# search Search Docker Hub for images
version Show the Docker version information
info Display system-wide information
Management Commands:
# builder Manage builds
container Manage containers
# context Manage contexts
image Manage images
# manifest Manage Docker image manifests and manifest lists
network Manage networks
# plugin Manage plugins
system Manage Docker
# trust Manage trust on Docker images
volume Manage volumes
Commands:
attach Attach local standard input, output, and error streams to a running container
# commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
# create Create a new container
# diff Inspect changes to files or directories on a container's filesystem
# events Get real time events from the server
# export Export a container's filesystem as a tar archive
# history Show the history of an image
import Import the contents from a tarball to create a filesystem image
# inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
logs Fetch the logs of a container
# pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
save Save one or more images to a tar archive (streamed to STDOUT by default)
# start Start one or more stopped containers
# stats Display a live stream of container(s) resource usage statistics
# stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
# unpause Unpause all processes within one or more containers
# update Update configuration of one or more containers
# wait Block until one or more containers stop, then print their exit codes
docker compose
docker compose コマンドについて
# 起動
docker compose up
# volume を使うと、自動的には削除されない。下記のコマンドを使うと、running ではないコンテナと volume も削除できる
docker system prune --volumes
# docker compose で起動したコンテナを停止、あわせて不要な volume も削除する
docker compose down -v
docker-compose.yml
restart
Container がクラッシュしたときの振る舞い。 restart だと必ず再度立ち上げようとする。
user
Compose file version 3 reference | Docker Documentation にあるとおり、これは docker run の USER に値する。 そして、これは User の UID や username を指定できる。
depends_on
起動順序の定義が行える。終了時は逆順となる。
特に web が db に依存する場合は、depends_on: [ db ]
のようになることが多い。
ちなみに、web から db へアクセスしたいとき、db:5432
のように指定することで名前解決ができる。
services:
db:
image: postgres:15
environment:
POSTGRES_DB: dev
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
django:
build: .
command: python manage.py runserver 0.0.0.0:8000
environment:
# host名は docker で起動された db となる
DATABASE_URL: "postgres://postgres:postgres@db:5432/dev"
SECRET_KEY: "sample_secret_key"
volumes:
- .:/djangoapp
ports:
- "8000:8000"
depends_on:
- db
docker の仕組み
docker のネットワーク
Docker のネットワークはよくハマる。
Docker compose ではアプリケーション1つに対して、ネットワークを作成する。 各コンテナ上のサービスはデフォルトネットワークに参加したら、同一ネットワーク上の他のコンテナから接続できるようになります。また、ホスト名とコンテナ名でも発見可能になります。
network driver
Driver には、bridge か overlay が指定できる。デフォルトでは bridge。
bridge ネットワークとは
「docker0 に値する」とあるが、どのような意味だ…
Use bridge networks | Docker Documentation
A bridge network is a Link Layer device which forwards traffic between network segments. A bridge can be a hardware device or a software device running within a host machine’s kernel.
ネットワークセグメント間で通信を転送する Link layer device とある。 Docker は software bridge を使っていて、定義された bridge network 内につながっているコンテナはお互いに通信が行える。
bridge モードのときは、同じ docker daemon を利用しているコンテナは同じ bridge network になる
異なる daemon 間で通信したい場合は、OS などの設定でルーティングさせるか、overlay ネットワークを使うらしい。
ブリッジ接続 (bridge connection)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
Use bridge networks | Docker Documentation
The default bridge network is considered a legacy detail of Docker and is not recommended for production use. Configuring it is a manual operation, and it has technical shortcomings.
デフォルトの bridge network はレガシーとある。
daemon.json で docker daemon が利用する bridge network の設定が記載されている。
To configure the default bridge network, you specify options in daemon.json. Here is an example daemon.json with several options specified. Only specify the settings you need to customize.
{
"bip": "192.168.1.5/24",
"fixed-cidr": "192.168.1.5/25",
"fixed-cidr-v6": "2001:db8::/64",
"mtu": 1500,
"default-gateway": "10.20.1.1",
"default-gateway-v6": "2001:db8:abcd::89",
"dns": ["10.20.1.2","10.20.1.3"]
}
192.168.1.0 - 192.168.1.255 のレンジを利用しているようだ。
user define bridge で通信
Containers connected to the same user-defined bridge network automatically expose all ports to each other, and no ports to the outside world. This allows containerized applications to communicate with each other easily, without accidentally opening access to the outside world.
同じ bridge network では全てのポートがお互いに通信できるが、外の世界からはポートが空いていないように見える。
Dockerfile の書き方
作り方の参考資料
- Best practices for writing Dockerfiles | Docker Documentation
- セキュリティ面でのベストプラクティス Dockerfileのベストプラクティス Top 20 | Sysdig
ADD はレイヤーが増えるが、 COPY はレイヤーを増やさない
docker image のファイルサイズを小さくする
go の src に vendor があるのでサイズは大きくなる。でも /go/bin が使われるだけなので、/go/src はまとめて不要 (- 300MB)
[root@7a4baa5582f7 /]# du -sh /go/bin/* | sort -h
3.7M /go/bin/yaml-patch
13M /go/bin/om
28M /go/bin/bosh-cli
[root@7a4baa5582f7 /]# du -sh /go/src/* | sort -h
2.2M /go/src/gopkg.in
31M /go/src/golang.org
299M /go/src/github.com
/usr/local/go は go 言語をインストールしたため存在する。 しかし、image build 後は go を実行しないので不要となる(go の binary は作られているため) (- 300 MB)
[root@7a4baa5582f7 /]# du -sh /usr/local/go/* | sort -h
6.5M /usr/local/go/api
12M /usr/local/go/test
31M /usr/local/go/bin
75M /usr/local/go/src
214M /usr/local/go/pkg
/usr/lib 内は Python, jvm でそもそもの動作に必要なので、削除できない。
5.7M /usr/lib/udev
9.1M /usr/lib/systemd
155M /usr/lib/python2.7
166M /usr/lib/jvm
yum の cache も不要 (- 80MB)
[root@7a4baa5582f7 /]# du -sh /var/cache/* | sort -h
16K /var/cache/ldconfig
81M /var/cache/yum
multi stage build でどこからでも確実にビルドできるようにする
multi stage を利用するととても便利。dockerfile を build するだけで必要なものを揃えることができる。
- make build 方式 <- バイナリのダウンロードなど高速化できるが、make を実行する環境依存
- multi stage build <- 環境を整えるのが冗長だが、docker build するだけで済む
multi stage build で ARG を利用する時
ARG JDK_VERSION="15"
ARG PLANTUML_VERSION="1.2020.2"
FROM openjdk:${JDK_VERSION}-jdk-alpine
RUN apk add --update-cache graphviz wget && \
wget "http://downloads.sourceforge.net/project/plantuml/$PLANTUML_VERSION/plantuml.$PLANTUML_VERSION.jar"
このコードは動かなくて、ARG は最初の FROM で認識されるにとどまる。正しくは下記のようにする。
ARG JDK_VERSION="15"
FROM openjdk:${JDK_VERSION}-jdk-alpine
ARG PLANTUML_VERSION="1.2020.2"
RUN apk add --update-cache graphviz wget && \
wget "http://downloads.sourceforge.net/project/plantuml/$PLANTUML_VERSION/plantuml.$PLANTUML_VERSION.jar"
.dockerignore を定義することで、docker image に入れるファイルを制限できる
.git
**/secret.yaml
と書くことで、どこのフォルダでも除くことができる。.gitignore とやや書式が異なるので注意
この場合、.git フォルダを除かないと git reset でシークレットが復元できたりしてしまうので注意(そもそもなんで secret 入ってんねんって話だが)