3

为什么要使用docker

众所周知,我们编写与运行任何软件都需要配置相应的环境,那么我们为什么不直接手动配置呢?

比如我们在同时编写两个web项目,一个使用数据库为mysql:5.7,另一个使用的数据库为mysql:8.0,但是mysql并不支持同时在本地运行多个版本,那么当我们每次更换项目时都需要删除当前mysql=》安装所需mysql=》重新配置mysql。

另一方面配置环境时可能会出多少问题我们应该都体会过,就上述这些过程来说无疑会浪费大量时间。更不用说当进行团队合作时组员间安装版本出差错时所浪费的时间。

所以我们就需要一个统一配置环境并且方便使用的物品,这就是docker。
我们只需要确定好配置文件,执行一条命令就可以配置好所有环境。

什么是dockerfile

Dockerfile的作用与docker-compose类似,也同样是为了配置环境而存在的,那么docker-file有什么特殊之处呢?
dockerFile官方文档

就目前所知,docker-compose我们在使用时需配置image项也就是我们需要的环境项例如我们需要mysql环境就配置为mysql:XXX,其他同理。

我们想要配置什么样的环境就需要在docker-hub官方网址中寻找相应的配置项,并按其示例进行配置,换句话说如果我们所需的环境在docker-hub官方网址中不存在我们就不能只使用docker-compose来进行配置。

比如我们想要一键配置好运行angular单元测试的环境,我们就无法在docker-hub官方网址中找到对应的环境。

这时候我们就需要自己配置镜像(image)通过Dockerfile并上传到阿里云-容器镜像服务中,从而可以在远程直接通过其公网地址加版本号(例:registry.cn-beijing.aliyuncs.com/mengyunzhi_li/node_ding_push:14.16.2)进行调用我们自定义的image。

如何编写简单的dockerfile

明白了dockerfile的功能,下一步就是要了解dockerfile如何编写
dockerFile官方文档
首先我们要知道一些基础指令
1: FROM:用于指定基础镜像,在我们自定义的镜像需要以某个镜像为基础时进行配置

例如: FROM  node:14.16.0-stretch

2:RUN:有多种使用方式,个人理解为在image构建时执行的命令

例如:RUN "command" "param1" "param2"

注意:构建时执行指在拉取环境到本地创建容器时不会执行,因为image早已经在阿里云镜像服务中构建完了。

3:CMD:与RUN类似,区别是其中的命令会在启动容器时执行

例如:CMD "command" "param1" "param2"

注意:
1、CMD在Dockerfile中只能出现一次,有多个,只有最后一个会有效。
2、其作用是在启动容器的时候提供一个默认的命令项。如果用户执行docker run的时候提供了命令项,就会覆盖掉这个命令。没提供就会使用构建时的命令。

4:COPY:复制本机文件或目录或远程文件,添加到指定的容器目录

COPY ./send-ding.sh /

注:上面我们将本地的send-ding.sh上传到了容器中,这使得我们可以在dockerFile容器中调用此脚本
docker
--Dockerfile
--send-ding.sh

实际问题

下面我的目标是创建一个image,可以让它在被调用时自动执行指定脚本进行钉钉推送。
由于之前没有使用经验,于是先尝试推送静态信息即不进行传参。

FROM node:14.16.0-stretch
RUN apt-get update
RUN apt install -y curl
RUN apt-get clean
COPY ./send-ding.sh /
RUN sh send-ding.sh -a 1ab5179dd94ed62de026d96ba61b41b1dda42357fdf79a787f11c7708449a06d -t markdown -c pipeine运行失败 -T "tiT,,le"
CMD ["sh", "send-ding.sh", "-a","1ab5179dd94ed62de026d96ba61b41b1dda42357fdf79a787f11c7708449a06d", "-t", "markdown", "-c", "pipeine运行失败", "-T", "'tiT,,le'"]

注:RUN 和 CMD后的指令为两种形式,实际使用时都可以

本地测试

1、本地创建image

 sudo docker build . -t=ding-file:1.2

2、查看我们创建的image

sudo docker image ls

image.png
3、根据image创建容器

sudo docker run -it ding-file:1.2 

image.png
4、查看钉钉发现进行了推送即执行如期进行

推送到阿里云,构建自定义image

打开阿里云容器镜像服务,创建个人实例。
图片.png
1、创建镜像仓库
图片.png
2、与自己的代码仓库进行绑定从而进行上传所需文件
图片.png
3、设置构建规则,用于定位所需文件
图片.png
4、构建完成后使用公网地址加版本号进行调用
图片.png
发现一切正常执行,如期执行了.sh文件进行了钉钉推送。

尝试在gitlab.yaml中使用此image

gitlab.yaml:

. . .

# 设置步骤(步骤间串行)
stages:
  - unit-test
  - notify


# 设置自动执行的管道名称
angular-test:
  # 前台使用docker来构建
  tags:
    - docker
  # 设置该管道属于的步骤,同步骤的管道并行执行
  stage: unit-test
  image: registry.cn-beijing.aliyuncs.com/mengyunzhi/node-chrome:14.16.0

  before_script:
    - cd web
  script:
    - pwd
    - npm install
    - npm run test -- --no-watch --no-progress --browsers=ChromeHeadlessCI

success-notify:
  # 前台使用docker来构建
  tags:
    - docker
  # 设置该管道属于的步骤,同步骤的管道并行执行
  stage: notify
  image: registry.cn-beijing.aliyuncs.com/mengyunzhi_li/node_ding_push:14.16.3
  script:
    - env

error-notify:
  # 前台使用docker来构建
  tags:
    - docker
  # 设置该管道属于的步骤,同步骤的管道并行执行
  stage: notify
  image: registry.cn-beijing.aliyuncs.com/mengyunzhi_li/node_ding_push:14.16.3
  script:
    - env
  when: on_failure

执行结果:
图片.png
发现没有出现执行上的错误但是也没有进行钉钉推送,根据日志显示在执行中也调用了我们自定义的镜像,但不知道为什么没有进行相应推送。
图片.png

查找原因时出现的问题

起初是怀疑dockerfile不支持将.sh文件加入到镜像中或者是由于操作失误没有正确加入,但是后来在本地调用阿里云上的镜像发现进行了钉钉推送可以得知已经将.sh文件加入到了镜像之中。
猜测:CMD是在容器创建时执行,但是有可能会被覆盖,就官方文档中提示的那样
图片.png
1、如果像在每次执行容器时运行相同的程序需要ENTRYPOINT和CMD结合使用
2、如果用户为docker run指定参数,则它们将覆盖CMD中指定的默认值
3、不要混淆RUN和CMD,RUN在构建时执行,CMD构建时不会执行任何操作,但是会指定相应命令给image即在运行容器时才会执行
所以猜测gitlab调用image时可能会传入某些默认参数导致此命令被覆盖。
待测试:将CMD改为ENTRYPOINT再次进行构建并重新运行pipeline观察是否会进行推送


李明
441 声望19 粉丝