railwayapp / nixpacks

App source + Nix packages + Docker = Image
https://nixpacks.com
MIT License
2.33k stars 222 forks source link

Option to skip `COPY . /app` #1037

Open emdede opened 6 months ago

emdede commented 6 months ago

Feature request

It would be great to be able to exclude directories/files that are not supposed to end up in the image.

It was my impression that you would be able to set onlyIncludeFiles = [] for a phase so you could overwrite default behavior but no matter what phase I hook into, in the end there's always a COPY . /app and I can't find a way to disable this behavior. I went through the docs and GH issues but I can't find a solution. Is there a way that I am not seeing or is it not possible? This is relevant for monorepos containing different applications. But even not taking into account monorepos, I think this would potentially help keep images leaner as a whole.

As an example, this is a very simple project structure to show a clear use-case of this:

|-- common/
|-- project1/
  |-- src/
  |-- nixfile.toml
|-- project2/
  |-- src/
  |-- nixfile.toml
|-- package.json
|-- package-lock.json

If I want to build project1 (nixpacks build -c=./project1/nixfile.toml .) which is independent of project2, I can't currently ignore project2's code.

github-actions[bot] commented 6 months ago

Hello, @emdede! Thanks for your submission.

Our team will respond soon. If you need more immediate help, try our Forum or our Discord. Thanks!

aleksrutins commented 6 months ago

Are you sure it's including them in the final image and not just for the build step?

emdede commented 6 months ago

Are you sure it's including them in the final image and not just for the build step?

Positive. I checked in the running container.

nixpacks plan

{
  "providers": [],
  "buildImage": "ghcr.io/railwayapp/nixpacks:ubuntu-1702339400",
  "variables": {
    "NIXPACKS_METADATA": "python,poetry",
    "NIXPACKS_POETRY_VERSION": "1.7.1",
    "PYTHONUNBUFFERED": "1"
  },
  "phases": {
    "install": {
      "dependsOn": [
        "setup"
      ],
      "cmds": [
        "python -m venv --copies /opt/venv && . /opt/venv/bin/activate && pip install poetry==$NIXPACKS_POETRY_VERSION && poetry install --without dev --no-interaction --no-ansi"
      ],
      "onlyIncludeFiles": [
        "common",
        "my-app",
        "poetry.lock",
        "pyproject.toml"
      ],
      "cacheDirectories": [
        "/root/.cache/pip"
      ],
      "paths": [
        "/opt/venv/bin"
      ]
    },
    "setup": {
      "nixPkgs": [
        "python310",
        "gcc",
        "libmysqlclient.dev"
      ],
      "nixLibs": [
        "zlib",
        "stdenv.cc.cc.lib"
      ],
      "nixOverlays": [],
      "nixpkgsArchive": "5148520bfab61f99fd25fb9ff7bfbb50dad3c9db"
    }
  },
  "start": {
    "cmd": "my-start-command"
  }
}

.nixpacks/Dockerfile

FROM ghcr.io/railwayapp/nixpacks:ubuntu-1702339400

ENTRYPOINT ["/bin/bash", "-l", "-c"]
WORKDIR /app/

COPY .nixpacks/nixpkgs-5148520bfab61f99fd25fb9ff7bfbb50dad3c9db.nix .nixpacks/nixpkgs-5148520bfab61f99fd25fb9ff7bfbb50dad3c9db.nix
RUN nix-env -if .nixpacks/nixpkgs-5148520bfab61f99fd25fb9ff7bfbb50dad3c9db.nix && nix-collect-garbage -d

ARG NIXPACKS_METADATA NIXPACKS_POETRY_VERSION PYTHONUNBUFFERED
ENV NIXPACKS_METADATA=$NIXPACKS_METADATA NIXPACKS_POETRY_VERSION=$NIXPACKS_POETRY_VERSION PYTHONUNBUFFERED=$PYTHONUNBUFFERED

# setup phase
# noop

# install phase
ENV NIXPACKS_PATH /opt/venv/bin:$NIXPACKS_PATH
COPY common /app/common
COPY my-app /app/my-app
COPY poetry.lock /app/poetry.lock
COPY pyproject.toml /app/pyproject.toml
RUN --mount=type=cache,id=tE9G8SvyOg4-/root/cache/pip,target=/root/.cache/pip python -m venv --copies /opt/venv && . /opt/venv/bin/activate && pip install poetry==$NIXPACKS_POETRY_VERSION && poetry install --without dev --no-interaction --no-ansi

RUN printf '\nPATH=/opt/venv/bin:$PATH' >> /root/.profile

# start
COPY . /app
CMD ["my-start-command"]

I've added these to the nixfile.toml with no change

[phases.build]
onlyIncludeFiles = []

[start]
onlyIncludeFiles = []
coffee-cup commented 5 months ago

This looks to be a bug with Nixpacks where it will always copy over all files before starting if there is no other runImage specified.

dush-t commented 5 months ago

Would love to attempt a fix if this is up for taking. Can you provide a minimum list of steps to reproduce this? I believe a simple ignore key in the nixfile should be sufficient to fix this.

jclaveau commented 1 month ago

This looks to be a bug with Nixpacks where it will always copy over all files before starting if there is no other runImage specified.

I confirm that this remove the unexpected COPY . /app which, in my case, breaks while trying to recopy over symlinks created during the build step.

I'm runing nixpacks 1.21.3

Btw, I personnaly have a COPY . /app at each step:

FROM ghcr.io/railwayapp/nixpacks:ubuntu-1711411379

ENTRYPOINT ["/bin/bash", "-l", "-c"]
WORKDIR /app/

COPY .nixpacks/nixpkgs-5148520bfab61f99fd25fb9ff7bfbb50dad3c9db.nix .nixpacks/nixpkgs-5148520bfab61f99fd25fb9ff7bfbb50dad3c9db.nix
RUN nix-env -if .nixpacks/nixpkgs-5148520bfab61f99fd25fb9ff7bfbb50dad3c9db.nix && nix-collect-garbage -d
COPY .nixpacks/nixpkgs-bf744fe90419885eefced41b3e5ae442d732712d.nix .nixpacks/nixpkgs-bf744fe90419885eefced41b3e5ae442d732712d.nix
RUN nix-env -if .nixpacks/nixpkgs-bf744fe90419885eefced41b3e5ae442d732712d.nix && nix-collect-garbage -d
RUN sudo apt-get update && sudo apt-get install -y --no-install-recommends libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libgbm1 libasound2 libpangocairo-1.0-0 libxss1 libgtk-3-0 libxshmfence1 libglu1

ARG CI NIXPACKS_METADATA NODE_ENV NPM_CONFIG_PRODUCTION PYTHONUNBUFFERED
ENV CI=$CI NIXPACKS_METADATA=$NIXPACKS_METADATA NODE_ENV=$NODE_ENV NPM_CONFIG_PRODUCTION=$NPM_CONFIG_PRODUCTION PYTHONUNBUFFERED=$PYTHONUNBUFFERED

# python:setup phase
# noop

# setup phase
# noop

# install phase
ENV NIXPACKS_PATH /app/node_modules/.bin:$NIXPACKS_PATH
COPY . /app/.
RUN --mount=type=cache,id=BzTYrNyrok-/root/local/share/pnpm/store/v3,target=/root/.local/share/pnpm/store/v3 npm install -g corepack
RUN --mount=type=cache,id=BzTYrNyrok-/root/local/share/pnpm/store/v3,target=/root/.local/share/pnpm/store/v3 corepack enable
RUN --mount=type=cache,id=BzTYrNyrok-/root/local/share/pnpm/store/v3,target=/root/.local/share/pnpm/store/v3 corepack prepare pnpm@9.1.0 --activate
RUN --mount=type=cache,id=BzTYrNyrok-/root/local/share/pnpm/store/v3,target=/root/.local/share/pnpm/store/v3 pnpm install --frozen-lockfile

# python:install phase
# noop

# build phase
COPY . /app/.
RUN --mount=type=cache,id=BzTYrNyrok-node_modules/cache,target=/app/node_modules/.cache pnpm --filter .... build

RUN printf '\nPATH=/app/node_modules/.bin:$PATH' >> /root/.profile

# start
COPY . /app
CMD ["pnpm start"]