# syntax = docker/dockerfile:1

<% if (packager === "bun") { -%>
# Adjust BUN_VERSION as desired
ARG BUN_VERSION=<%= bunVersion %>
FROM oven/bun:${BUN_VERSION}-<%= variant %> as base
<% } else { -%>
# Adjust NODE_VERSION as desired
ARG NODE_VERSION=<%= distroless ? (parseInt(nodeVersion) & ~1) : nodeVersion %>
FROM node:${NODE_VERSION}-<%= variant %> as <% if (distroless) { -%>build<% } else { %>base<% } %>
<% } -%>

<% if (Object.keys(options.args.base).length > 0) { -%>
# Base arguments 
<%- emitArgs(options.args.base) %>
    
<% } -%>
<% if (!distroless) { -%>
LABEL fly_launch_runtime="<%= runtime %>"

<% } -%>
<% if (basePackages.length > 0) { -%>
# Install packages needed for both build and deployment
RUN <% if (options.cache) { %><%= pkg_cache %>
    <% } %><%= pkg_update %> && \
    <%= pkg_install %> <%= basePackages.join(' ')%><% if (!options.cache) { %> && \
    rm -rf <%= pkg_cleanup %><% } %>

<% } -%>
# <%= runtime %> app lives here
WORKDIR /app

# Set production environment
<%- emitEnv(baseEnv) %>
<% if (yarn) { -%>
ARG YARN_VERSION=<%= yarnVersion %>
<% if(yarnVersion.startsWith('3.')) {-%>

# Install Yarn 3
RUN corepack enable && \
    yarn set version ${YARN_VERSION}
<% } else { -%>
RUN npm install -g yarn@$YARN_VERSION --force
<% } -%>
<% } else if (pnpm) { -%>

# Install pnpm
ARG PNPM_VERSION=<%= pnpmVersion %>
RUN npm install -g pnpm@$PNPM_VERSION
<% } %>
<% if (options.instructions.base) { -%>
<%- options.instructions.base %>

<% } -%>
<% if (!distroless) { -%>

# Throw-away build stage to reduce size of final image
FROM base as build

<% } -%>
<% if (Object.keys(options.args.build).length > 0) { -%>
# Build arguments
<%- emitArgs(options.args.build) %>

<% } -%>
<% if (Object.keys(buildEnv).length > 0) { -%>
<%- emitEnv(buildEnv) %>

<% } -%>
# Install packages needed to build node modules
RUN <% if (options.cache) { %><%= pkg_cache %>
    <% } %><%= pkg_update %> && \
    <%= pkg_install %> <%= buildPackages.join(' ') %>

# Install node modules
COPY<% if (options.link) { %> --link<% } %> <%= packageFiles.join(' ') %> ./
RUN <%- buildCache %><%= packagerInstall %>

<% if (prisma) { -%>
# Generate Prisma Client
COPY<% if (options.link) { %> --link<% } %> prisma .
RUN <%= npx %> prisma generate

<% } -%>
# Copy application code
COPY<% if (options.link) { %> --link<% } %> . .

<% if (build && !options.deferBuild) { -%>
# Build application
RUN <%- mountSecrets %><%= build %>

<% if (devDependencies && !options.dev && !nestjs && !adonisjs) { -%>
# Remove development dependencies
RUN <%- buildCache %><%- packagerPrune %>

<% } -%>
<% } -%>
<% if (options.instructions.build) { -%>
<%- options.instructions.build %>

<% } -%>

# Final stage for app image
<% if (distroless) { -%>
FROM gcr.io/distroless/nodejs${NODE_VERSION}

LABEL fly_launch_runtime="<%= runtime %>"

# <%= runtime %> app lives here
WORKDIR /app

# Set production environment
<%- emitEnv(baseEnv) %>
<% } else if (vite || astroStatic) { -%>
FROM nginx
<% } else { -%>
FROM base
<% } -%>

<% if (litefs) { -%>
# Install, configure litefs
COPY --from=flyio/litefs:0.4.0 /usr/local/bin/litefs /usr/local/bin/litefs
COPY --link <%= configDir %>litefs.yml /etc/litefs.yml

<% } -%>
<% if (deployPackages.length > 0) { -%>
# Install packages needed for deployment
RUN <% if (options.cache) { %><%= pkg_cache %>
    <% } %><%= pkg_update %> && \
    <%= pkg_install %> <%= deployPackages.join(' ')%><% if (!options.cache) { %> && \
    rm -rf <%= pkg_cleanup %><% } %>

<% } -%>
# Copy built application
<% if (vite || astroStatic) { -%>
COPY --from=build /app/dist /usr/share/nginx/html
<% } else if (astroSSR) { -%>
COPY --from=build /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist

ENV PORT=4321
ENV HOST=0.0.0.0
<% } else { -%>
COPY --from=build /app /app
<% } -%>

<% if (false && !options.root) /* needs more testing */ { -%>
# Run as a non-root user for security
RUN addgroup --system --gid 1001 nodejs && \
    useradd <%= user %> --gid nodejs --home /app --shell /bin/bash
USER <%= user %>:nodejs

<% } -%>
<% if (adonisjsFileUpload) { -%>
RUN mkdir -p /app/tmp/uploads
VOLUME /app/tmp/uploads
<% } -%>
<% if (sqlite3) { -%>
# Setup sqlite3 on a separate volume
RUN mkdir -p /data<% if (litefs) { %> /litefs <% } %>
VOLUME /data

<% } -%>
<% if (sqlite3) { -%>
<% if (remix) { -%>
# add shortcut for connecting to database CLI
RUN echo "#!/bin/sh\nset -x\nsqlite3 \$DATABASE_URL" > /usr/local/bin/database-cli && chmod +x /usr/local/bin/database-cli

<% } -%>
<% } -%>
<% if (options.instructions.deploy) { -%>
<%- options.instructions.deploy %>

<% } -%>
<% if (entrypoint) { -%>
<% if (entrypointFixups.length) { -%>
# Adjust entrypoint to be executable on Linux
RUN <%- entrypointFixups.join(' && \\\n    ') %>

<% } -%>
<% if (prisma) { -%>
# Entrypoint prepares the database.
<% } else { -%>
# Entrypoint sets up the container.
<% } -%>
ENTRYPOINT <%- entrypoint %>

<% } -%>
<% if (Object.keys(options.args.deploy).length > 0) { -%>
# Deploy arguments 
<%- emitArgs(options.args.deploy) %>
            
<% } -%>
<% if (options.nginxRoot) { -%>
# configure nginx
RUN sed -i 's/access_log\s.*;/access_log stdout;/' /etc/nginx/nginx.conf && \
    sed -i 's/error_log\s.*;/error_log stderr info;/' /etc/nginx/nginx.conf

COPY <<-"EOF" /etc/nginx/sites-available/default
server {
  listen <%= port %> default_server;
  listen [::]:<%= port %> default_server;
  access_log stdout;

  root <%= options.nginxRoot %>;

  location / {
    try_files $uri @backend;
  }

  location @backend {
    proxy_pass http://localhost:<%= port + 1 %>;
    proxy_set_header Host $http_host;
  }
}
EOF

<% } -%>
<% if (foreman) { -%>
# Build a Procfile for production use
COPY <<-"EOF" /app/Procfile.prod
<% if (options.nginxRoot) { -%>
nginx: /usr/sbin/nginx -g "daemon off;"
<% } -%>
app: PORT=<%= port+1 %> <%- startCommand.join(" ") %>
EOF

<% } -%>
# Start the server by default, this can be overwritten at runtime
EXPOSE <%= port %>
<% if (Object.keys(deployEnv).length > 0) { -%>
<%- emitEnv(deployEnv) %>
<% } -%>
<% if (foreman) { -%>
CMD [ "<%= npx %>", "foreman", "start", "--procfile", "Procfile.prod" ]
<% } else if (Array.isArray(startCommand)) { -%>
CMD <%- JSON.stringify(startCommand, null, 1).replaceAll(/\n\s*/g, " ") %>
<% } else { -%>
CMD <%- startCommand %>
<% } -%>
