Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asset paths #449

Merged
merged 1 commit into from
Sep 12, 2023
Merged

Asset paths #449

merged 1 commit into from
Sep 12, 2023

Conversation

djmb
Copy link
Collaborator

@djmb djmb commented Sep 11, 2023

During deployments both the old and new containers will be active for a small period of time. There also may be lagging requests for older CSS and JS after the deployment.

This can lead to 404s if a request for old assets hits a new container or visa-versa.

This PR makes sure that both sets of assets are available throughout the deployment from before the new version of the app is booted.

This can be configured by setting the asset path:

asset_path: "/rails/public/assets"

The process is:

  1. We extract the assets out of the container, with docker run, docker cp, docker stop. Docker run sets the container command to "sleep" so this needs to be available in the container.
  2. We create an asset volume directory on the host for the new version of the app on the host and copy the assets in there.
  3. If there is a previous deployment we also copy the new assets into its asset volume and copy the older assets into the new asset volume.
  4. We start the new container mapping the asset volume over the top of the container's asset path.

This means the both the old and new versions have replaced the asset path with a volume containing both sets of assets and should be able to serve any request during the deployment. The older assets will continue to be available until the next deployment.

h/t to @jeremy for simplifying the original idea for this 🙏

basecamp/kamal-site#26

During deployments both the old and new containers will be active for a
small period of time. There also may be lagging requests for older CSS
and JS after the deployment.

This can lead to 404s if a request for old assets hits a new container
or visa-versa.

This PR makes sure that both sets of assets are available throughout the
deployment from before the new version of the app is booted.

This can be configured by setting the asset path:

```yaml
asset_path: "/rails/public/assets"
```

The process is:
1. We extract the assets out of the container, with docker run, docker
cp, docker stop. Docker run sets the container command to "sleep" so
this needs to be available in the container.
2. We create an asset volume directory on the host for the new version
of the app on the host and copy the assets in there.
3. If there is a previous deployment we also copy the new assets into
its asset volume and copy the older assets into the new asset volume.
4. We start the new container mapping the asset volume over the top of
the container's asset path.

This means the both the old and new versions have replaced the asset
path with a volume containing both sets of assets and should be able
to serve any request during the deployment. The older assets will
continue to be available until the next deployment.
djmb added a commit to basecamp/kamal-site that referenced this pull request Sep 11, 2023
@nickhammond
Copy link
Contributor

Nice work, is there a recommended way to point to this volume for caching with precompilation? As in utilizing this asset volume to reduce asset compilation time. I usually have something like this in my Dockerfile:

RUN --mount=type=cache,id=bld-assets-cache,sharing=locked,target=tmp/cache/assets \
    ./bin/rails assets:precompile

@djmb
Copy link
Collaborator Author

djmb commented Sep 12, 2023

Nice work, is there a recommended way to point to this volume for caching with precompilation? As in utilizing this asset volume to reduce asset compilation time. I usually have something like this in my Dockerfile:

The asset volumes are on the hosts that are deployed to, not where we build (unless you are using the same host for both).

You could use a similar approach to this PR and extract the assets from the latest image and copy them onto the cache mount in a pre-build hook. But if you are usually persisting the cache between builds I'm not sure that is going to buy you that much.

@djmb djmb merged commit 00cb7d9 into main Sep 12, 2023
6 checks passed
@djmb djmb deleted the asset-path branch September 12, 2023 07:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants