www.alexis-otaku.top /2021/06/03/makefile-is-docker-s-friend

Makefile 是 docker 的好朋友

Alex 9-11 minutes 2021/6/3

docker 作为主要开发环境的同学时常力不从心,因为 docker 运行在虚拟容器中,一切操作都涉及到以下几个步骤:

如果是临时执行还可以接受,但如果是需要频繁执行的命令,敲这种庞大的命令串无疑是开发的噩梦。有两种方案可以缓解这种状况。

编写 shell 脚本

使用 shell 可以顺利简化陈长的 docker 命令所造成的问题。我们要编写 shell 脚本,然后通过脚本参数的形式调用其中的 shell 函数, 执行封装在函数中的命令。下面是一个使用 jekyll 的简单的例子:

#!env bash

VERSION="stable"
DOCKER_TAG="alex/ruby:$VERSION"

# Build docker image if it doesn't exist
build() {
  if [[ `docker images -q alexlayton/ruby:stable 2> /dev/null` == "" ]]; then
    docker build -t $DOCKER_TAG .;
  fi
}

serve() {
  build
  docker run --rm --volume="$PWD:/srv/jekyll" -w /srv/jekyll -it\
    -p 35729:35729 -p 4000:4000 alexlayton/ruby:stable\
    bundle exec jekyll serve\
      -I --unpublished -l --livereload-port 35729  -H 0.0.0.0 -P 4000\
      --config _config.yml,_config_dev.yml
}

$*

其中最后一句 $* 是必要的,这句命令允许我们通过参数指定需要调用的函数。然后我们可以像这样启动 jekyll develop server:

编写脚本的好处是可以完全控制命令的执行,一次编写之后可以反复调用,然而编写运行脚本对于开发的本职任务来说,是不小的额外工作量。 实际上,有一款工具已经为我们实现了上述脚本的工作模式,它就是 Makefile.

Make / Makefile

make 是一种按照依赖顺序依次构建目标(target)的工具,Makefile 则是 make 的配置文件。使用 make 同样可以达到上述 shell 脚本的效果,并承担了调用和维护依赖项的职责。

仍以 jekyll develop server 为例,首先创建 Makefile

version       := stable
docker_tag    := alexlayton/ruby:$(version)
docker_runner := docker run --rm --volume="$PWD:/srv/jekyll" -w /srv/jekyll -it
jekyll_runner := bundle exec jekyll

port     ?= 4000
liveport ?= 35729

# build image from dockerfile
define docker_build
    if [ "$(shell docker images -q $(docker_tag) 2> /dev/null)" = "" ]; then \
        docker build -t $(docker_tag) .; \
    fi
endef

.PHONY: build serve

build: build_image
	$(docker_runner) $(docker_tag) bundle install

serve: build
	$(docker_runner) -p $(port):$(port) -p $(liveport):$(liveport) $(docker_tag) $(jekyll_runner) serve \
		-I --unpublished -l --livereload-port $(liveport) -H 0.0.0.0 -P $(port)\
		--config _config.yml,_config_dev.yml

build_image:
	$(docker_build)

上面的 Makefile 中有三个 target 分别是 build, servebuild_image,其中 build 依赖于 build_imageserve 依赖于 build_imagebuild,需要先构建镜像再构建项目,然后启动 develop server,这里由于 build 传递了对 build_image 的依赖,所以 serve 只依赖于 build 即可。

可以看到,Makefile 帮我们做了依赖管理,如果要启动 develop server,我们只要执行 make serve 即可。这在构建复杂的开发环境时很有帮助, 很多开源项目也在使用这种管理方式。

总结

以上两种都是主流方案,可以根据项目情况选择合适的管理方式,一般情况下,使用 make 就能满足大部分项目的需求。顺带说一下, docker compose 和 make 并不是同类工具,compose 是以容器为单位的一种编排工具,不应该作为简化命令行的方案。

::...
免责声明:
当前网页内容, 由 大妈 ZoomQuiet 使用工具: ScrapBook :: Firefox Extension 人工从互联网中收集并分享;
内容版权归原作者所有;
本人对内容的有效性/合法性不承担任何强制性责任.
若有不妥, 欢迎评注提醒:

或是邮件反馈可也:
askdama[AT]googlegroups.com


订阅 substack 体验古早写作:


点击注册~> 获得 100$ 体验券: DigitalOcean Referral Badge

关注公众号, 持续获得相关各种嗯哼:
zoomquiet


自怼圈/年度番新

DU22.4
关于 ~ DebugUself with DAMA ;-)
粤ICP备18025058号-1
公安备案号: 44049002000656 ...::