12/10/2021

Yarn Install Docker

34

Our love for Rails, Docker and Kubernetes is no secret! In this post, I wanted to share some of our experience on how to deal with Rails 6 assets that use webpacker in Docker in a production environment.

What are we trying to achieve?

By the end of this post, we are going to run a Rails 6 application with compiled assets from inside of a Docker container under Production environment.

User Management in Docker Container. YARN’s Docker container support launches container processes using the uid:gid identity of the user, as defined on the NodeManager host. User and group name mismatches between the NodeManager host and container can lead to permission issues, failed container launches, or even security holes. Let's start by creating a folder for our project and initialise yarn. Mkdir yarn-docker-setup cd yarn-docker-setup yarn init -p. Enter fullscreen mode. Exit fullscreen mode. If you do not have yarn installed already, you can install by npm install yarn -g. After filling out basic questions, you would have a package.json file.

What do you need?

Consider these recommendations before installing and configuring Docker for use with YARN. Install Docker Identify the version of Docker provided by your operating system vendor and install it. Configure Docker After Docker is installed, edit the Docker's daemon configuration (daemon.json) file to add the recommended configuration.

A Rails 6 application. You can use this sample app if you want: https://github.com/cloud66-samples/rails6-mysql

NOTE: If you use this example repository, all the files mentioned in this post are already created for you.

You'd also need to have Docker installed on your machine.
Basic understanding of using Docker command line and Dockefile format is also required.

While ultimately we are going to run this on a Kubernetes cluster (or Minikubes), the setup is the same and this post is going to focus on the tips of running Rails 6 in a containerized environment rather than focusing on the details of Kubernetes. For this reason, we're going to use Docker Compose instead of Kubernetes to make things simpler as the Rails settings are the same in both environments.

Let's get started

Running in Dev

First, let's run our application in development mode to make sure everything it runs with no errors and we have the basics configured correctly.

To get going, create a file called Dockerfile in the application root directory like this one:

This installs the latest version of Ruby. If you want to change that, you can do so on the first line of the file. This might be needed if you explicitly have specified a ruby version in your Gemfile. Also here you see I am installing version 2.1.2 of Bundler gem. Feel free to use the version your Gemfile is compatible with (Rails 6 defaults to Bundler 2).

Our example app, like many others, uses MySQL as a database. To run both Rails and MySQL in docker on our laptop, we can use Docker Compose. Create a file called, docker-compose.yml in your application root directory like this one:

Please mind that this is only for development purposes and that's why you can see the password in clear text in this file!

To make sure Rails can see the database, we need to make sure our database.yml is configured correctly:

These is one last thing to do before we can run the app: create the database. This is needed only once unless you wipe the MySQL image off your laptop.

Now we can start the app:

On your laptop, visit http://localhost:3000 and you should see the app running.

Running in Production

You might have noticed that like any other Rails app running in development the application compiles the assets upon the first call. In production, we would want this to happen during the image build to speed things up.

To make this change, we're going to add the following line to our dockerfile as the last line:

This will run the asset precompilation and adds the compiled assets to the image.

Let's run the application again, this time in production. To run the application in production, change the value of RAILS_ENV to production in your docker-compose.yml.

Visiting http://localhost:3000 you will notice none of the assets are served correctly. This is because Rails by default doesn't serve static assets in production. This is done with the assumption that your web server (nginx, Apache, etc) is going to take care of the static assets before they hit the Rails stack to speed things up.

A note on secrets

A new Rails 6 application, won't run in production environment, unless you configre a secret_key_base for it and use the Rails 6's Master key. This can be done by doing the following:

  1. Generate a new secret by running rake secret copy the output
  2. Run rails credentials:edit --environment production and enter the value from step 1 as the value of the secret_key_base key in the file.
  3. Make sure RAILS_MASTER_KEY is passed in as a variable to your container. This is used by Rails to decrypt production.yml.enc file.

Once you close the editor, the content of the file will be encrypted and written to production.yml.enc under config/credentials. Rails also adds production.key to your .gitignore file to avoid leaking secrets into your git repo. You also need to make sure master.key is not commited into your git repo either, agian, by adding it to .gitignore file.

Subnote on VS Code and Rails Credentials Editor

If you're using Visual Studio Code (or similar editors like Sublime or Atom) as your default editor, you might need to set the value of EDITOR environment variable to make sure the secrets editor still works:

In case of VS Code, -w ensures the editor process stays up until the file is closed so it can be encrypted and written back to the disk.

Serving Static Assets in Production in Kubernetes

In a containerized environment, it is possible to run nginx in front of your Rails application and share a volume between the 2 containers (Rails and nginx) with changes in the nginx configuration to serve the static assets using nginx and not Rails. However, when running in a real production environment (as opposed to only setting RAILS_ENV to production on our laptop), if you're running your application on Kubernetes, you're also probably running it behind an Ingress Controller, which most probably means your nginx is shared between multiple applications. This means we need to make Rails serve static assets itself.

To make that change set RAILS_SERVE_STATIC_FILES to true in your docker-compose.yml and run the application again:

This time, running docker-compose up will start Rails and serves the static assets.

Where are my logs?

Rails by default logs to log files in production. In a containerized environment, you'd want to make sure logs are written to stdout and stderr instead so they can be collected by your orchestrator (like Kubernetes or in this example, Compose). To make that change, set RAILS_LOG_TO_STDOUT to true in your docker-compose.yml file:

Now you should see your logs!

Summary

In summary, to run Rails 6 in production in a containerized environment like Kubernetes, you need to do the following:

  1. Make sure yarn is installed in your Docker image (see the Dockerfile example above)
  2. Install Bundler 2 and above. Most Docker Ruby base images come with Bundler 1.
  3. Run yarn install --check-files in your Dockerfile
  4. Run RAILS_ENV=production bundle exec rake assets:precompile in your Dockerfile.
  5. Set RAILS_SERVE_STATIC_FILES to true
  6. Set RAILS_LOG_TO_STDOUT to true if you would like to see the logs.
  7. Make sure you either have a credentials file in production or set the SECRET_KEY_BASE variable in production and during the image build phase.

Can it be made simpler?

If this looks too much, you can always use Cloud 66 Skycap to run your Rails applications on any Kubernetes cluster. Skycap understands Rails: it connects to your git and generates the needed Dockerfile, environment variables and all of the needed Kuberentes configuration files you'd to run your Rails app in production on Kubernetes in a simple few steps.

Related Articles:

yarn install is used to install all dependencies for a project. This is mostcommonly used when you have just checked out code for a project, or whenanother developer on the project has added a new dependency that you need topick up.

If you are used to using npm you might be expecting to use --save or--save-dev. These have been replaced by yarn add and yarn add --dev. Formore information, seethe yarn add documentation.

Running yarn with no command will run yarn install, passing through any provided flags.

If you need reproducible dependencies, which is usually the case with the continuous integration systems, you should pass --frozen-lockfile flag.

yarn install

Install all the dependencies listed within package.json in the localnode_modules folder.

The yarn.lock file is utilized as follows:

  • If yarn.lock is present and is enough to satisfy all the dependencies listed in package.json, the exact versions recorded in yarn.lock are installed, and yarn.lock will be unchanged. Yarn will not check for newer versions.
  • If yarn.lock is absent, or is not enough to satisfy all the dependencies listed in package.json (for example, if you manually add a dependency to package.json), Yarn looks for the newest versions available that satisfy the constraints in package.json. The results are written to yarn.lock.

If you want to ensure yarn.lock is not updated, use --frozen-lockfile.

yarn install --check-files

Verifies that already installed files in node_modules did not get removed.

yarn install --flat

Install all the dependencies, but only allow one version for each package. On the first run this will prompt you tochoose a single version for each package that is depended on at multipleversion ranges. These will be added to your package.json under aresolutions field.

yarn install --force

This refetches all packages, even ones that were previously installed.

yarn install --har

Outputs an HTTP archive from all thenetwork requests performed during the installation. HAR files are commonly usedto investigate network performance, and can be analyzed with tools such asGoogle’s HAR Analyzer orHAR Viewer.

yarn install --ignore-scripts

Do not execute any scripts defined in the project package.json and its dependencies.

yarn install --modules-folder <path>

Specifies an alternate location for the node_modules directory, instead of the default ./node_modules.

yarn install --no-lockfile

Don’t read or generate a yarn.lock lockfile.

yarn install --production[=true false]

Yarn will not install any package listed in devDependencies if the NODE_ENV environment variable is set to production. Use this flag to instruct Yarn to ignore NODE_ENV and take its production-or-not status from this flag instead.

Notes:--production is the same as --production=true. --prod is an alias of --production.

yarn install --pure-lockfile

Don’t generate a yarn.lock lockfile.

yarn install --focus

Yarn Install Docker Tutorial

Shallowly installs a package’s sibling workspace dependencies underneath its node_modules folder. This allows you to run that workspace without building the other workspaces it depends on.

Must be run inside an individual workspace in a workspaces project. Can not be run in a non-workspaces project or at the root of a workspaces project.

yarn install --frozen-lockfile

Don’t generate a yarn.lock lockfile and fail if an update is needed.

yarn install --silent

Run yarn install without printing installation log.

Install
yarn install --ignore-engines

Ignore engines check.

yarn install --ignore-optional

Don’t install optional dependencies.

yarn install --offline

Run yarn install in offline mode.

yarn install --non-interactive

Disable interactive prompts, like when there’s an invalid version of a dependency.

yarn install --update-checksums

Update checksums in the yarn.lock lockfile if there’s a mismatch between them and their package’s checksum.

yarn install --audit

Checks for known security issues with the installed packages. A count of found issues will be added to the output. Use the yarn audit command for additional details. Unlike npm, which automatically runs an audit on every install, yarn will only do so when requested. (This may change in a later update as the feature is proven to be stable.)

yarn install --no-bin-links

Prevent yarn from creating symlinks for any binaries the package might contain.

Docker Install Yarn

yarn install --link-duplicates

Create hardlinks to the repeated modules in node_modules.

yarn install --verbose

Install Yarn Docker Rails

Show additional logs while installing dependencies

  • Most Viewed News

    • Install Gitlab Docker
    • Install Docker Compose Centos 7 Offline
    • Download Iwork For Mac Free Full Version
    • Python Alpine Gcc
    • Wordpress Docker Setup