前言
主要是記錄Docker遇到的坑,更多的是因為自己的粗心大意,以此警示
正文
Dockerfile里的RUN
某一次把啟動服務的命令寫在了 Dockerfile 中,后來發現服務一直拉不起來.
原來是把啟動命令寫在了 Dockerfile 的 RUN 里
Dockerfile 的 RUN 命令只有在打包時才會用到
Dockerfile 的 CMD 命令才是在鏡像啟動時執行,我們只需要將啟動命令放在 CMD 里即可
但是為了分開 (Dockerfile 只負責打包,執行由 Docker-compose ),我個人一般將啟動命令放在 Docker-compose 的 command 里
Docker 內部的服務不會更新
某一次寫了服務, 發現該服務有一個問題,修復后重新 go build 用 Docker 重新制作並測試
使用 Docker-compose 進行測試(docker-compose up ),只有編譯過后的二進制服務更新了, 其余沒更新
發現代碼在 Docker 里沒有更新(通過比對 md5 )
Dockerfile 文件如下
# 基礎系統鏡像
FROM debian:stable-slim
# 新建文件夾
RUN mkdir /root/gophish
# 設置工作目錄
WORKDIR /root/gophish
# COPY當前目錄所有文件到WORKDIR
COPY . .
# 設置執行權限並執行
RUN chmod +x gophish
# 注意:RUN后面的命令只有在構建鏡像時執行,CMD才是啟動時執行,也可以將啟動寫到DockerCompose中方便管理
原因是在多次 build 時, 基礎鏡像 stable-slim 里有上一次編譯的 gophish 二進制文件
也就是說, mkdir 並不會執行, WORKDIR也不會執行, 走到 COPY 時, Docker沒有檢測到二進制文件 gophish 更新了,
所以鏡像內部的 gohish 一直是老得版本
解決問題有多種方法, 比如把原來的鏡像刪除/COPY時不要一次全部COPY指定文件夾依次COPY等等,我是直接修改Dockerfile
# 基礎系統鏡像
FROM debian:stable-slim
# 新建文件夾, 防止Docker識別不出文件改動,在COPY前先刪除原有文件
RUN rm -rf /root/gophish/ && mkdir /root/gophish
# 設置工作目錄
WORKDIR /root/gophish
# COPY當前目錄所有文件到WORKDIR
COPY . .
# 設置執行權限並執行
RUN chmod +x gophish
# 注意:RUN后面的命令只有在構建鏡像時執行,CMD才是啟動時執行,也可以將啟動寫到DockerCompose中方便管理
COPY 的藝術
看到許多教程都建議 COPY . .
也就是將本地文件夾所有文件都 COPY 到 Docker 中
這種方式跟普通的一個文件夾一個文件夾的 COPY 相比, 雖然減少了幾行命令, 但是也有其缺點
就是會將所有文件都 COPY 比如 .git 文件夾等不需要 COPY 的文件夾和文件
比如
Docker-compose up 時代碼不會更新
如果在 docker-compose 中有
image: xxx:1.0
build: .
這代表image不存在時才會 build
如果存在老的版本你改動了代碼也不會重新build
解決方法是刪除 xxx 的image 或者運行 docker-compose build
docker-compose demo
version: "3" # 指定語法版本
services: # 定義service
db: # 定義名字叫db的service
image: mysql:8 # 鏡像是mysql版本8(默認數據庫格式為utf8mb4)
restart: always # 出現問題重新啟動
environment: # 設置環境變量
MYSQL_ROOT_PASSWORD: example # root密碼
MYSQL_DATABASE: gophish # 設置數據庫名
networks: # 配置所屬網絡組
- gophish_network
expose: # 開放該容器的端口給同個組
- 3306 # 同一個network下的service可以通過 db:3306 訪問, 主機無法訪問
volumes:
- ./data:/var/lib/mysql # 將Mysql數據掛載到宿主機
gophish:
image: gophish:1.0 # 與自己打包的Docker鏡像名字相同
build: . # 沒有找到鏡像就build所在目錄下的
restart: always # 出現問題重新啟動
depends_on: # 配置前置條件,
- db # db的service啟動后才啟動gophish
networks:
- gophish_network # 所屬網絡組
ports: # 放開端口給主機的映射關系, 主機可直接訪問
- 80:80 # 主機的80對應gophish的80
- 3333:3333
volumes: # 掛載文件
- ./config.json:/root/gophish/config.json # 將compose同級的config.json與該server的/root/gophish/config.json同步,service目錄是絕對路徑
command: /root/gophish/gophish # 執行啟動鏡像
# network_mode: "host" # 更改組網方式為host,默認的是橋接,分配一個虛擬ip,外部無法直接訪問, 不能和networks一起使用
# host方式與宿主機綁定,端口共享,可能出現端口占用
# https://www.jianshu.com/p/2d02bb9a9da5
networks: # 設置網絡組讓多個service通訊
gophish_network: # 設置一個網絡組