Closed dorianmariecom closed 7 months ago
Please provide some relevant additional information such as your deploy.yml file, your entrypoint file, etc.
Dockerfile
:
FROM debian:bullseye-slim as base
ENV BUNDLER_VERSION="2.5.5" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development" \
NODE_VERSION="20.11.0" \
NPM_VERSION="10.4.0" \
RAILS_ENV="production" \
RUBY_INSTALL_VERSION="0.9.3" \
RUBY_VERSION="3.3.0" \
YARN_VERSION="1.22.19"
ENV PATH="/opt/rubies/ruby-${RUBY_VERSION}/bin:/usr/local/node/bin:${PATH}"
RUN apt-get update && \
apt-get install -y \
autoconf \
build-essential \
curl \
fish \
git \
libpq-dev \
libvips \
pandoc \
pkg-config \
postgresql-client \
vim \
wget
RUN wget "https://github.com/postmodern/ruby-install/releases/download/v${RUBY_INSTALL_VERSION}/ruby-install-${RUBY_INSTALL_VERSION}.tar.gz" \
&& tar -xzvf "ruby-install-${RUBY_INSTALL_VERSION}.tar.gz" \
&& cd "ruby-install-${RUBY_INSTALL_VERSION}" \
&& make install
RUN ruby-install -p https://github.com/ruby/ruby/pull/9371.diff ruby "${RUBY_VERSION}"
WORKDIR /rails
FROM base as build
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
/tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
npm install -g "yarn@${YARN_VERSION}" && \
rm -rf /tmp/node-build-master
COPY Gemfile Gemfile.lock ./
RUN gem install bundler -v "${BUNDLER_VERSION}"
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
bundle exec bootsnap precompile --gemfile
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
RUN bundle exec bootsnap precompile app/ lib/
RUN HOST=example.com \
BASE_URL=https://example.com \
RAILS_MASTER_KEY_DUMMY=1 \
SECRET_KEY_BASE_DUMMY=1 \
./bin/rails assets:precompile
FROM base
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails
RUN useradd rails --create-home --shell /bin/bash && \
chown -R rails:rails db log storage tmp
USER rails:rails
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
EXPOSE 3000
CMD ["./bin/rails", "server"]
config/deploy.yml
service: code
image: dorianmariecom/code
builder:
remote:
arch: amd64
ssh: root@45.55.196.152
servers:
web:
hosts:
- 45.55.196.152
labels:
traefik.http.routers.code.rule: Host(`code.dorianmarie.com`)
traefik.http.routers.code_secure.entrypoints: websecure
traefik.http.routers.code_secure.rule: Host(`code.dorianmarie.com`)
traefik.http.routers.code_secure.tls.certresolver: letsencrypt
traefik.http.routers.code_secure.tls: true
registry:
username:
- KAMAL_REGISTRY_USERNAME
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
HOST: code.dorianmarie.com
BASE_URL: https://code.dorianmarie.com
secret:
- RAILS_MASTER_KEY
- POSTGRES_PASSWORD
traefik:
options:
publish:
- "443:443"
volume:
- "/letsencrypt/acme.json:/letsencrypt/acme.json"
args:
entryPoints.web.address: ":80"
entryPoints.websecure.address: ":443"
entryPoints.web.http.redirections.entryPoint.to: websecure
entryPoints.web.http.redirections.entryPoint.scheme: https
entryPoints.web.http.redirections.entrypoint.permanent: true
certificatesResolvers.letsencrypt.acme.email: "dorian@dorianmarie.com"
certificatesResolvers.letsencrypt.acme.storage: "/letsencrypt/acme.json"
certificatesResolvers.letsencrypt.acme.httpchallenge: true
certificatesResolvers.letsencrypt.acme.httpchallenge.entrypoint: web
accessories:
db:
image: postgres:16.1
host: 45.55.196.152
port: 5432
env:
clear:
POSTGRES_USER: code
POSTGRES_DB: code_production
secret:
- POSTGRES_PASSWORD
directories:
- data:/var/lib/postgresql/data
bin/docker-entrypoint
:
#!/bin/bash -e
if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then
./bin/rails db:prepare
fi
exec "${@}"
Hope that helps
Does your application respond to /up
endpoint? You can also configure another one if necessary as described here.
Another thing that helped figure out a similar issue was to ssh into my app instance and execute the Docker command that Kamal executes directly and then follow the logs output, in your example: docker run --detach --name healthcheck-code-6550a03c44a6673c16ee8074b20b7d72cd2145ce_uncommitted_a6e9c411a4db04e7 --publish 3999:3000 --label service=healthcheck-code -e KAMAL_CONTAINER_NAME="healthcheck-code" --env-file .kamal/env/roles/code-web.env --health-cmd "curl -f http://localhost:3000/up || exit 1" --health-interval "1s" dorianmariecom/code:6550a03c44a6673c16ee8074b20b7d72cd2145ce_uncommitted_a6e9c411a4db04e7
I'm getting:
bin/rails aborted!
ActiveRecord::ConnectionNotEstablished: could not connect to server: No such file or directory (ActiveRecord::ConnectionNotEstablished)
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
Caused by:
PG::ConnectionBad: could not connect to server: No such file or directory (PG::ConnectionBad)
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
Tasks: TOP => db:prepare
(See full trace by running task with --trace)
I don't understand, I have my db accessory defined
@dorianmariecom You can't use the socket(/var/run/postgresql/.s.PGSQL.5432
) with a docker container, you'll have to use the IP or add a bridge network.
Take a look at your database.yml, your host will need to point to 45.55.196.152.
@dorianmariecom I see multiple issues in your configuration.
First, like @nickhammond mentioned you are using a single server setup - which requires additional configuration. You have to update your database credentials to point to the SERVER_IP with the POSTGRES_PORT. Or, which I recommend, create a docker network and assign all containers to that network. With this approach you still have to update the database credentials but would use the container name instead of the SERVER_IP.
Second (next upcoming issue), you are using rails user in your dockerfile but are deploying / setting up containers & volumes with root user, which will result in rails not being able to setup/access the storage because of user uid mismatch on host and container. Anyway I encourage you to create a new user on your host as containerized deployment processes do not need any root permissions at all. This new user needs to have the same uid as your rails user defined in your dockerfile.
@nickhammond By using the right user (code, not root, not rails) I'm able to connect to the database, thanks a lot <3
deploy successful :), now onto the second point by @n1xn
Second (next upcoming issue), you are using rails user in your dockerfile but are deploying / setting up containers & volumes with root user, which will result in rails not being able to setup/access the storage because of user uid mismatch on host and container. Anyway I encourage you to create a new user on your host as containerized deployment processes do not need any root permissions at all. This new user needs to have the same uid as your rails user defined in your dockerfile.
I'm really not sure how to do that
Maybe ChatGPT can help you out... Let's assume you will ignore creating a new user on the host - you would have to do the following:
id -u root
on hostRUN useradd -u UID_FROM_STEP_1 rails...
Actually I just use root for everything now and it's fine
@dorianmariecom How do you resolve the issue?
I've got a similar issue. My app container doesn't get started with a port mapping:
INFO [47f02b4b] Running docker run --detach --restart unless-stopped --name my-node-server-app-web-fc3ac1385c495d6e5a7263e71d4ce9c7f5f91105 --hostname 5.161.245.237-1d0b3f16f933 -e KAMAL_CON
TAINER_NAME="my-node-server-app-web-fc3ac1385c495d6e5a7263e71d4ce9c7f5f91105" -e KAMAL_VERSION="fc3ac1385c495d6e5a7263e71d4ce9c7f5f91105" --env-file .kamal/env/roles/my-node-server-app-web.env
--health-cmd "(curl -f http://localhost:3000/healthz || exit 1) && (stat /tmp/kamal-cord/cord > /dev/null || exit 1)" --health-interval "1s" --volume $(pwd)/.kamal/cords/my-node-server-app-we
b-cb1b90b87060bc49b66c43d5bbb37398:/tmp/kamal-cord --log-opt max-size="10m" --label service="my-node-server-app" --label role="web" --label destination --label traefik.http.services.my-node-se
rver-app-web.loadbalancer.server.scheme="http" --label traefik.http.routers.my-node-server-app-web.rule="PathPrefix(\`/\`)" --label traefik.http.routers.my-node-server-app-web.priority="2" --l
abel traefik.http.middlewares.my-node-server-app-web-retry.retry.attempts="5" --label traefik.http.middlewares.my-node-server-app-web-retry.retry.initialinterval="500ms" --label traefik.http.r
outers.my-node-server-app-web.middlewares="my-node-server-app-web-retry@docker" marko911/node-app:fc3ac1385c495d6e5a7263e71d4ce9c7f5f91105 on 5.161.245.237
So the container starts but it can't be accessed via http. My deploy yaml is:
# Name of your application. Used to uniquely configure containers.
service: my-node-server-app
# Name of the container image. <dockerhub username>/<app-name>
image: marko911/node-app
# Deploy to these servers. <Copy Hetzner ip address of VM >
servers:
- 5.161.245.237
# Credentials for your image host.
registry:
# Specify the registry server, if you're not using Docker Hub
# server: registry.digitalocean.com / ghcr.io / ...
username: marko911
# Always use an access token rather than real password when possible.
password:
- DOCKER_HUB_TOKEN
# Inject ENV variables into containers (secrets come from .env).
# Remember to run `kamal env push` after making changes!
env:
secret:
- SECRET_PHRASE
- HOST_PORT
I'm getting unhealthy containers and I can't seem to fix it, any help?