dokku / dokku

A docker-powered PaaS that helps you build and manage the lifecycle of applications
https://dokku.com
MIT License
29.3k stars 1.92k forks source link

Dokku uses a Ubuntu 14 images instead of the Dockerfile from the buildpack #3018

Closed NiklasRosenstein closed 6 years ago

NiklasRosenstein commented 6 years ago

Description of problem:

My buildpack has the following Dockerfile:

FROM heroku/heroku:16-build

WORKDIR /app
ENV WORKSPACE_DIR="/app/builds" \
    S3_BUCKET="lang-python" \
    S3_PREFIX="heroku-16/"

RUN apt-get update && apt-get install -y python-pip && rm -rf /var/lib/apt/lists/*

COPY requirements.txt /app/
RUN pip install --disable-pip-version-check --no-cache-dir -r /app/requirements.txt

COPY . /app

The heroku/heroku:16-build inherits from heroku/heroku:16 which in turn inherits from ubuntu:16.04. But the container in which my app is built and run is a Ubuntu 14.04 version.

$ dokku run discord-gmusic-bot lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:        14.04
Codename:       trusty

Environment details (AWS, VirtualBox, physical, etc.): physical

How was Dokku installed?: Dokku install script

How reproducible: Always

Does Dokku not actually use the Dockerfile from the buildpack? If not, how does it compose the container for apps?

josegonzalez commented 6 years ago

We trigger the bin/compile step of your buildpack within herokuish, as does Heroku. We only respect the Dockerfile shipped with your application.

NiklasRosenstein commented 6 years ago

@josegonzalez That bin/compile is already triggered from inside a container, right? So if my app does not have a Dockerfile in its source directory, what image does dokku use in that case?

NiklasRosenstein commented 6 years ago

PS: Since you're closing this issue immediately, it appears you don't want questions in the GitHub issue tracker. In that case, I suggest updating the README, as it is currently saying

image

josegonzalez commented 6 years ago

Apologies if that didn't answer your question - I'm actually in-between meetings at work, so I def answered in haste - but i closed assuming I did.

If you push an app, it will pull your Dockerfile - if it exists - unless you have a .buildpacks file in the repository or have set a BUILDPACK_URL environment variable. If you end up using a buildpack, it will use gliderlabs/herokuish, which is based on Ubuntu 14.04.

josegonzalez commented 6 years ago

Let me know if that answers your questions, happy to answer anything further. Feel free to close if the above answers everything.

NiklasRosenstein commented 6 years ago

Thanks for clarifying! So if I were using my own Dockerfile, do I need to make sure to install the herokuish CLI? Or does Dokku not assume anything in that case and just build the Dockerfile as-is?

josegonzalez commented 6 years ago

There isn't a herokuish CLI. It's just a standard docker base image we use for buildpacks.

For docker file deploys, it just uses the docker file as is. See our docs site for more info, as there are usage caveats as well.

josegonzalez commented 6 years ago

@NiklasRosenstein docs for dockerfile deploys are here.

josegonzalez commented 6 years ago

@NiklasRosenstein anything else?

NiklasRosenstein commented 6 years ago

There isn't a herokuish CLI. It's just a standard docker base image we use for buildpacks.

Ah, for some reason I thought that this program would need to be available inside a container, but it seems herokuish is a tool for orchestrating containers (see https://github.com/gliderlabs/herokuish#using-herokuish).

Thanks also for the link to the docs.

Nothing for now, thanks for your time! :)

NiklasRosenstein commented 6 years ago

Actually, I thought I could just copy&paste the contents of the herokuish Dockerfile, but that doesn't quite work as I expected it to. I'm sorry but I don't really have much experience with using docker.

What I really want to do is to use a buildpack, but use a different base image. As you said, the default image is gliderlabs/herokuish. This image is based on heroku/cedar:14, which explains why my app is deployed in a Ubuntu 14.04 container.

I tried adding the following Dockerfile to my app.

FROM heroku/heroku:16-build

ENV BUILDPACK_URL=https://github.com/nodepy/nodepy-buildpack

# gliderlabs/herokuish
RUN curl "https://github.com/gliderlabs/herokuish/releases/download/v0.3.33/herokuish_0.3.33_linux_x86_64.tgz" \
        --silent -L | tar -xzC /bin
RUN /bin/herokuish buildpack install \
    && ln -s /bin/herokuish /build \
    && ln -s /bin/herokuish /start \
    && ln -s /bin/herokuish /exec
COPY include/default_user.bash /tmp/default_user.bash
RUN bash /tmp/default_user.bash && rm -f /tmp/default_user.bash

It doesn't appear to be doing quite what I expected.

Counting objects: 17, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (17/17), 5.96 KiB | 0 bytes/s, done.
Total 17 (delta 6), reused 0 (delta 0)
remote: Preparing /tmp/dokku_git.7iHP (identifier dokku_git.7iHP)
remote: -----> Cleaning up...
remote: -----> Building discord-gmusic-bot from dockerfile...
remote: Sending build context to Docker daemon  43.01kB
remote: Step 1/6 : FROM heroku/heroku:16-build
remote:  ---> 7b639a676c4c
remote: Step 2/6 : ENV BUILDPACK_URL=https://github.com/nodepy/nodepy-buildpack
remote:  ---> Running in 93e5ce42cd12
remote: Removing intermediate container 93e5ce42cd12
remote:  ---> 5f2ea4b97254
remote: Step 3/6 : RUN curl "https://github.com/gliderlabs/herokuish/releases/download/v0.3.33/herokuish_0.3.33_linux_x86_64.tgz"
        --silent -L | tar -xzC /bin
remote:  ---> Running in 9c16f42c64ee
remote: Removing intermediate container 9c16f42c64ee
remote:  ---> 1c617c41f489
remote: Step 4/6 : RUN /bin/herokuish buildpack install         && ln -s /bin/herokuish /build  && ln -s /bin/herokuish /start  && ln -s /bin/herokuish /exec
remote:  ---> Running in 8d8baeecf0f4
remote: Cloning into '/tmp/buildpacks/00_buildpack-multi'...
remote: Cloning into '/tmp/buildpacks/01_buildpack-ruby'...
remote: Cloning into '/tmp/buildpacks/02_buildpack-nodejs'...
remote: Cloning into '/tmp/buildpacks/03_buildpack-clojure'...
remote: Cloning into '/tmp/buildpacks/04_buildpack-python'...
remote: Cloning into '/tmp/buildpacks/05_buildpack-java'...
remote: Cloning into '/tmp/buildpacks/06_buildpack-gradle'...
remote: Cloning into '/tmp/buildpacks/07_buildpack-scala'...
remote: Cloning into '/tmp/buildpacks/08_buildpack-play'...
remote: Cloning into '/tmp/buildpacks/09_buildpack-php'...
remote: Cloning into '/tmp/buildpacks/10_buildpack-go'...
remote: Cloning into '/tmp/buildpacks/11_buildpack-erlang'...
remote: Cloning into '/tmp/buildpacks/12_buildpack-static'...
remote: Removing intermediate container 8d8baeecf0f4
remote:  ---> 40a39977c3a2
remote: Step 5/6 : COPY include/default_user.bash /tmp/default_user.bash
remote: COPY failed: stat /var/lib/docker/tmp/docker-builder911788110/include/default_user.bash: no such file or directory

I suppose I could just clone the buildpack and run bin/compile in the Dockerfile, but does that function properly with Dokku's slugs and releases?

NiklasRosenstein commented 6 years ago

Maybe something simpler to answer, which could eventually help me get my own Dockerfile working quickly: Where is the app's worktree available in the docker container? Shouldn't it be available under /app? Because this Dockerfile

FROM heroku/heroku:16-build
RUN ls

gives

$ git push -f
Counting objects: 17, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (17/17), 5.83 KiB | 0 bytes/s, done.
Total 17 (delta 6), reused 0 (delta 0)
remote: Preparing /tmp/dokku_git.UpPW (identifier dokku_git.UpPW)
remote: -----> Cleaning up...
remote: -----> Building discord-gmusic-bot from dockerfile...
remote: Sending build context to Docker daemon   42.5kB
remote: Step 1/2 : FROM heroku/heroku:16-build
remote:  ---> 7b639a676c4c
remote: Step 2/2 : RUN ls
remote:  ---> Running in e0c47a081a22
remote: bin
remote: boot
remote: dev
remote: etc
remote: home
remote: lib
remote: lib64
remote: media
remote: mnt
remote: opt
remote: proc
remote: root
remote: run
remote: sbin
remote: srv
remote: sys
remote: tmp
remote: usr
remote: var
remote: Removing intermediate container e0c47a081a22
remote:  ---> 8ff24df5e0ca
remote: Successfully built 8ff24df5e0ca
[...]

There's no app directory.

NiklasRosenstein commented 6 years ago

Nevermind, I failed to notice the example at the bottom of the docs page you linked. It needs to be

FROM heroku/heroku:16-build
WORKDIR /app
COPY . ./
RUN ls
NiklasRosenstein commented 6 years ago

Alright, I have got it working with a lot of trial & error. I am sure there are better ways to do this, so if you have any comments, they are most welcome. For example, I do not know how this plays, or could play, together with Dokkus' slugs and releases, and the buildpacks' CACHE_DIR is probably not actually cached/kept alive for the next build since the containers' filesystem is ephemeral.

I may also want to delete the files in the CACHE_DIR and the /buildpack so that the directories do not exist in the deployed container instance.

FROM heroku/heroku:16-build

WORKDIR /app
COPY . ./

ENV BUILDPACK_URL=https://github.com/nodepy/nodepy-buildpack
ENV BUILD_DIR=/app
ENV CACHE_DIR=/app-cache
ENV ENV_DIR=/app-env

RUN apt-get update && apt-get install -y libopus-dev libssl-dev ffmpeg
RUN /bin/bash -c 'git clone $BUILDPACK_URL /buildpack'
RUN /bin/bash -c '/buildpack/bin/compile $BUILD_DIR $CACHE_DIR $ENV_DIR'

ENV PATH="/app/.heroku/python/bin:.nodepy/bin:${PATH}"
josegonzalez commented 6 years ago

You probably want to re-order your Dockerfile a bit so that you get better caching:

FROM heroku/heroku:16-build

WORKDIR /app

ENV BUILDPACK_URL=https://github.com/nodepy/nodepy-buildpack
ENV BUILD_DIR=/app
ENV CACHE_DIR=/app-cache
ENV ENV_DIR=/app-env

RUN apt-get update && apt-get install -y libopus-dev libssl-dev ffmpeg
RUN /bin/bash -c 'git clone $BUILDPACK_URL /buildpack'

COPY . ./
RUN /bin/bash -c '/buildpack/bin/compile $BUILD_DIR $CACHE_DIR $ENV_DIR'

ENV PATH="/app/.heroku/python/bin:.nodepy/bin:${PATH}"

Dokku doesn't use slugs, we just build an image and use that resulting image. We do some custom steps for herokuish to mount a cache into the build - basically each bit is a docker run && docker commit step - but thats not possible for Dockerfile builds, so there isn't any "caching" other than whatever you come up with in your Dockerfile.

If you have further questions, perhaps our chat room is a better venue to continue these discussions. I'm pretty active on slack, so fee free to hop on there.

Closing as there isn't much more here to do in the context of Dokku.