Loading

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:  # 设置一个网络组

posted @ 2020-03-17 11:18  ChnMig  阅读(1370)  评论(0编辑  收藏  举报