docker_note

2018-05-19

最近建服務越來越覺得docker好用

想說來寫個note,以後忘記了可以直接翻這個看不用再google了

相關好文:
http://oomusou.io/docker/dockerfile-dockercompose/
https://docs.docker.com/config/containers/container-networking/
https://www.cnblogs.com/guoguojj/p/9404781.html
https://www.jianshu.com/p/adb0350557dc
https://godleon.github.io/blog/Docker/docker-network-overview/
https://blog.yowko.com/change-container-port-mapping/

下載image檔:

docker pull [image]

跑image檔:

docker run [options] [image id]

其中run裡面有一些參數算比較常用的 在此紀錄一下

-d是print id後在背景執行
-p就是指定port forward給host,也可以ip forward
--hostname=[hostname] 可以指定hostname,注意!create container之後就不能改hostname了
--name=[name] 可以指定container name

ex.
docker run -p 127.0.0.1:8080:80 [image id]

這在run一些server服務的時候蠻實用的

被container雷了,因此特別做個筆記,container如果沒加上--privileged,就算是root用戶也還是有受到限制
另一個問題是預設情況下docker會禁止container使用系統指令
所以還必須加上 --security-opt seccomp:unconfined
再來就是ptrace,這個是gdb能不能hook elf很重要的參數
所以我們也要讓docker允許container修改他
--cap-add=SYS_PTRACE,另一件事:如果你想修改hostname也必須在run image的時候define好
--hostname=[hostname]
--name=[container name]

我現在run image都用下這個:

docker run --cap-add=SYS_PTRACE --security-opt seccomp:unconfined --privileged --hostname=kali --name=kali -it 5424cd86f9e1 bash

查看現在擁有的image

docker image list

查看現在正在執行的container

docker container list

停用container

docker container stop [container id]

查看所有container&image 包含沒執行的

docker ps -a

如果要移除container

docker rm [container id]

移除全部的container

docker rm $(docker ps -a -q)

如果要移除image

dokcer rmi [image id]

移除全部的image

docker rmi $(docker images -q)

清除特定 container 的 log ( debug 用 )

truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

列出 docker 目前容量的佔用情況

docker system df -v

像ctfd有自己的docker-compose 不用pull image可以直接產container
只要進去資料夾內進行指定command

docker-compose up

之後要啟動(停止)服務要到該資料夾內

docker-compose start(stop)

如果想(不想)要docker container 開機就啟動的話可以用下面的參數處理

docker update --restart=yes(no) [container ID] 

想要在 container 與 host 之間複製檔案

docker cp [container name]:[location] [host location]

遇到dockerfile需要先build他

docker build -t [name] . --no-cache

使用--no-cache是因為避免在 Build Docker image 時被 cache 住,而造成沒有 build 到修改過的 Dockerfile

之後docker會吐給你一串image的token,run那個token之後就可以啟動服務了

剛剛run docker container ps -a 發現container的名稱好亂,剛剛又找了rename的方法,意外簡單

docker rename [old name] [new name]

如何在正在進行中的container裡面開一個shell?

docker exec -it [container id] bash

如果要指定登入的user要再加--user [username](記得要先在機器裡面adduser)
如果要讓shell 呈現256色彩的話則是-e TERM="xterm-256color", -e = env

我目前的設定大概是這樣:

#!/bin/bash
docker container start f9f07a4d171a
docker exec -it --user astar -e TERM="xterm-256color"  f9f07a4d171a bash

如果升級了images的版本,docker 並不會幫你把舊的image刪掉,導致image的庫會很多垃圾image

這時候可以試試 prune 移除 dangling component

各個compoent都有對應的 prune

docker container prune
docker image prune
docker network prune
docker volume prune

要移除所以沒在使用的 Images 不是只有 dangling 的 Images,可以在 prune 加上 -a

來源:
https://stackoverflow.com/questions/32723111/how-to-remove-old-and-unused-docker-images
https://blog.clarence.tw/2019/09/10/docker-removing-containers-images-volumes-and-networks/

以我自己的為例子

before:

after:

根據 docker 官方的說法是,資料部分盡量不要留在 container,所以這時候就需要 mount 的指令了
推薦這個筆記,很詳盡,這邊列出我會用到的而已
https://medium.com/alberthg-docker-notes/docker%E7%AD%86%E8%A8%98-%E8%AE%93%E8%B3%87%E6%96%99%E9%81%A0%E9%9B%A2container-%E4%BD%BF%E7%94%A8-volume-bind-mount-%E8%88%87-tmpfs-mount-6908da341d11

綁定的參數分為 -v--mount
根據上面的文章可以想成 -v--mount 的簡化版

使用 --mount 的話需要給更詳盡的參數

使用 -v 進行掛載
$ docker run -d -v [host dir]:[container dir] [image name]

docker run --rm -it -p 8081:80 -v /tmp/test:/var/www vulnerables/web-dvwa
如果 host 的路徑不存在資料夾的話會創建一個

docker run –mount type=bind,source=[host dir],target=[container dir] [image name]
(type 有 bind volume tmpfs,預設值為 volume)
docker run --rm -it -p 8081:80 --mount type=bind,source=/tmp/test,target=/var/www vulnerables/web-dvwa

下這個 command 是把 host 的資料夾資訊取代原有 container 的資料夾內容,以 dvwa 這個為例,這個 command 下去,container 內的 /var/www 就會被取代成 host 的 /tmp/test

如果是想做到像是 VM 那樣 mount 一個共用資料夾並保留 container 原本的資料的話需要用 volume

創建 volume
docker volume create --name testVolumn

這時候在 /var/lib/docker/volumes/ 裡面就有我們創好的 volume 了,只是裡面的 _data 內容還是空的
mount 的路徑可以透過 docker inspect [container name] | grep -i Volumn 知道

這時候下
docker run --rm -it -p 8081:80 -v testVolumn:/var/www vulnerables/web-dvwa
或 mount 多個
docker run --rm -it -p 8081:80 -v testVolumn:/var/www -v testVolumn2:/etc/ vulnerables/web-dvwa
再次進去 _data 裡面看就會發現裡面的內容跟 container 內的 /var/www 會是一樣的,並且複寫的的邏輯依照我自己嘗試的結果應該是這樣

如果 container 有這個檔案 host 沒有 → container 的檔案直接寫
如果 container 有這個檔案 host 也有 → 依 host 檔案為主

另外如果 docker run 有加上 --rm 就算退出 container volume 的內容也不會消失

移除 volume
docker volume rm [volume name]

注意先確認沒有 container mount 他了

大概是這樣 如果後面有用到還會再補充

在 zsh 上自動補完

最近從ubnutu轉移到mac上(對發光蘋果沒有抵抗><)發現很多東西都還要學習www

光zsh對docker 的autocomplete 的設定又花了我一點時間
大概參考了這篇:

https://tommy.net.cn/2015/02/24/enable-zsh-completion-of-brew-under-mac-os-x/
https://docs.docker.com/compose/completion/

成果: