I’ve been working on a little Amber app and got to the point where I want to deploy it with Docker. We have an internal server that’s already running a bunch of services using Docker and keeping them up to date with Watchtower.
So after a bit of copy pasting and experimenting, I end up with a Dockerfile like this:
FROM crystallang/crystal:1.11.2-alpine as builder
RUN mkdir /build
WORKDIR /build
RUN apk add --no-cache sqlite-static yaml-static
COPY shard.yml shard.lock ./
RUN shards install --production
COPY src/ src/
COPY config/ config/
COPY db/ db/
COPY public/ public/
RUN shards build --release --production --static --no-debug combine
RUN rm -rf lib db/*.db
RUN mkdir storage && chown 1000:1000 storage
FROM scratch
USER 1000:1000
COPY --from=builder /build /
COPY --from=builder /etc/ssl/cert.pem /etc/ssl/
VOLUME /storage
EXPOSE 80
ENV AMBER_ENV=production
ENTRYPOINT ["/bin/combine"]
Which builds fine. But when I run it, I get this:
~/d/r/combine ▶ docker run --rm --init --env "AMBER_ENCRYPTION_KEY=le-secret" -v (pwd)/storage:/storage --name combine combine-test:latest
06:30:00 amber.server | (Info) Amber 1.4.1 serving application "Combine" at http://0.0.0.0:8006:30:00 amber.server | (Info) Server started in production.
06:30:00 amber.server | (Info) Startup Time 00:00:00.000043466
06:30:00 amber.server | (Info) Amber 1.4.1 serving application "Combine" at http://0.0.0.0:8006:30:00 amber.server | (Info) Server started in production.
06:30:00 amber.server | (Info) Startup Time 00:00:00.000029683
06:30:00 amber.server | (Info) Amber 1.4.1 serving application "Combine" at http://0.0.0.0:8006:30:00 amber.server | (Info) Amber 1.4.1 serving application "Combine" at http://0.0.0.0:8006:30:00 amber.server | (Info) Server started in production.
06:30:00 amber.server | (Info) Server started in production.
06:30:00 amber.server | (Info) Startup Time 00:00:00.000030255
06:30:00 amber.server | (Info) Startup Time 00:00:00.000030375
The variations in timings suggest that it’s actually running everything four times. And I have no idea why.
It doesn’t do it if I compile the app locally and run it. I’ve tried both static and dynamic compilation. I’ve ensured it’s the same Crystal version locally and in Docker.
Anyone have a clue?