Docker踩过的坑
前言
主要是记录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: # 设置一个网络组