如何为开发和生产配置不同的 dockerfile

我使用码头为开发和生产的幼鱼项目。对于开发和生产,我的 dockerfile 略有不同。例如,我在开发环境中将本地目录挂载到 docker 容器,这样我就不需要为每次代码更改都进行 docker build。

由于挂载的目录只有在运行 docker 容器时才可用,因此我不能在 dockerfile 中为开发而放置诸如“作曲器安装”或“ npm 安装”之类的命令。

目前我管理两个 docker 文件,是否有任何方法,我可以做到这一点与单一的 docker 文件,并决定哪些命令运行时,通过发送参数进行 docker 构建。

我想要达到的是强大

在码头档案里

...
IF PROD THEN RUN composer install
...

在码头建造期间

docker build [PROD] -t mytag .
61246 次浏览

UPDATE (2020): Since this was written 3 years ago, many things have changed (including my opinion about this topic). My suggested way of doing this, is using one dockerfile and using scripts. Please see @yamenk's answer.

ORIGINAL:

You can use two different Dockerfiles.

# ./Dockerfile (non production)
FROM foo/bar
MAINTAINER ...


# ....

And a second one:

# ./Dockerfile.production
FROM foo/bar
MAINTAINER ...


RUN composer install

While calling the build command, you can tell which file it should use:

$> docker build -t mytag .
$> docker build -t mytag-production -f Dockerfile.production .

As a best practice you should try to aim to use one Dockerfile to avoid unexpected errors between different environments. However, you may have a usecase where you cannot do that.

The Dockerfile syntax is not rich enough to support such a scenario, however you can use shell scripts to achieve that.

Create a shell script, called install.sh that does something like:

if [ ${ENV} = "DEV" ]; then
composer install
else
npm install
fi

In your Dockerfile add this script and then execute it when building

...
COPY install.sh install.sh
RUN chmod u+x install.sh && ./install.sh
...

When building pass a build arg to specify the environment, example:

docker build --build-arg "ENV=PROD" ...

You can use build args directly without providing additional sh script. Might look a little messy, though. But it works.

Dockerfile must be like this:

FROM alpine
ARG mode
RUN if [ "x$mode" = "xdev" ] ; then echo "Development" ; else echo "Production" ; fi

And commands to check are:

docker build -t app --build-arg mode=dev .
docker build -t app --build-arg mode=prod .

I have tried several approaches to this, including using docker-compose, a multi-stage build, passing an argument through a file and the approaches used in other answers. My company needed a good way to do this and after trying these, here is my opinion.

The best method is to pass the arg through the cmd. You can pass it through vscode while right clicking and choosing build image Image of visual studio code while clicking image build using this code:

ARG BuildMode
RUN echo $BuildMode
RUN if [ "$BuildMode" = "debug" ] ; then apt-get update \
&& apt-get install -y --no-install-recommends \
unzip \
&& rm -rf /var/lib/apt/lists/* \
&& curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l /vsdbg ; fi

and in the build section of dockerfile:

ARG BuildMode
ENV Environment=${BuildMode:-debug}
RUN dotnet build "debugging.csproj" -c $Environment -o /app


FROM build AS publish
RUN dotnet publish "debugging.csproj" -c $Environment -o /app