Skip to content

Commit

Permalink
Update Docker Compose and Devcontainer (#725)
Browse files Browse the repository at this point in the history
* Devcontainer

* WIP Docker broken?

* Initial split of Docker documentation

* WIP

* More .gitignore

* yarn update

* Update compose, etc.
  • Loading branch information
lcreid committed Mar 2, 2024
1 parent ba6f19a commit 34e9120
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 186 deletions.
38 changes: 38 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-docker-compose
{
"name": "bootstrap_form",

// Update the 'dockerComposeFile' list if you have more compose files or use different names.
"dockerComposeFile": ["../compose.yml", "../compose.override.yml"],

// The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "shell",

// The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/app",
// "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}"

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [],

// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
"shutdownAction": "none"

// Uncomment the next line to run commands after the container is created.
// "postCreateCommand": "cat /etc/os-release",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "reid"
}
25 changes: 18 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
.npm/_npx

.idea
log/*.log
pkg/
/doc/
/log/*.log
/pkg/
/tmp/

demo/db/*.sqlite3
demo/db/*.sqlite3-shm
demo/db/*.sqlite3-wal
demo/doc/screenshots/**/*.diff.png
demo/log/*.log
demo/storage
demo/tmp/

test/dummy/

*.gem
.rbenv-gemsets
*.swp
Expand All @@ -27,10 +34,6 @@ Vagrantfile

# For the demo app.

# Ignore uploaded files in development.
demo/storage/*
!demo/storage/.keep

demo/public/assets
**/.byebug_history

Expand All @@ -47,7 +50,7 @@ demo/.yarn-integrity
demo/vendor/bundle

# For stuff that gets created if using the Dockerfile image
.bundle/
/.bundle/
.cache/
vendor/bundle

Expand All @@ -62,4 +65,12 @@ vendor/bundle
.ash_history
.sqlite_history

compose.override.yml
docker-compose.override.yml

.vscode-server/
.dotnet/
.gnupg/
.ssh/
.gitconfig

2 changes: 1 addition & 1 deletion .yarnrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# yarn lockfile v1


lastUpdateCheck 1698606246341
lastUpdateCheck 1709415989700
113 changes: 4 additions & 109 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ cd demo
bundle exec rails test:all # or test:system
```

The [Docker development environment](#using-docker-compose) appears to generate screenshots that are the same as what GitHub generates.
The [Docker development environment](#using-docker compose) appears to generate screenshots that are the same as what GitHub generates.

Finally, maintainers may sometimes push changes directly to `main` or use other workflows to update the code. If pushing to `main` generates a commit for screenshot changes, please consider reverting your change immediately by executing the above `pull` and `revert` and another `push`, for the sanity of users who are using the edge (`main` branch) version of the gem. At any rate, review the changes promptly and use your judgement.

Expand Down Expand Up @@ -104,116 +104,11 @@ The Ruby on Rails support policy is [here](https://guides.rubyonrails.org/mainte

### Developing with Docker

This repository offers experimental support support for a couple of ways to develop using Docker, if you're interested:
This repository offers experimental support for development using Docker. Docker is _not_ required to do development work on this gem.

- Using `docker-compose`. This way is less tested, and is an attempt to make the Docker container a more complete environment where you can conveniently develop and release the gem.
- Using just a simple Dockerfile. This way works for simple testing, but doesn't make it easy to release the gem, among other things.
One advantage of the Docker environment is that it allows you to generate and compare the screenshots with the expected screenshots in the repo. It also allows you to develop in an environment that is isolated from your own computer's set-up, so there's less risk of breaking other things you might be doing with your computer.

Docker is _not_ required to work on this gem.

#### Using `docker-compose`

The `docker-compose` approach should link to enough of your networking configuration that you can release the gem.
However, you have to do some of the configuration yourself, because it's dependent on your host operating system.

First, build the image for whatever version of Ruby you need (typically either the earliest supported version or the latest):

```bash
RUBY_VERSION=3.2 docker-compose build
```

You can run a shell in a Docker container that pretty much should behave like a Debian distribution with:

```bash
docker-compose run --service-ports shell
```

(`--service-ports` exposes port 3000 so you can browse to the demo app on `localhost:3000`. If you just want to run a one-off command, or run the test suite, leave off the `--service-ports`.)

The following instructions work for an Ubuntu host, and will probably work for other common Linux distributions.

Add a `docker-compose.override.yml` in the local directory, that looks like this:

```docker-compose.yml
version: '3.3'
# https://blog.giovannidemizio.eu/2021/05/24/how-to-set-user-and-group-in-docker-compose/
services:
shell:
# You have to set the user and group for this process, because you're going to be
# creating all kinds of files from inside the container, that need to persist
# outside the container.
# Change `1000:1000` to the user and default group of your laptop user.
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- ~/.gem/credentials:/app/.gem/credentials:ro
# $HOME here is your host computer's `~`, e.g. `/home/reid`.
# `ssh` explicitly looks for its config in the home directory from `/etc/passwd`,
# so the target for this has to look like your home directory on the host.
- ~/.ssh:${HOME}/.ssh:ro
- ${SSH_AUTH_SOCK}:/ssh-agent
environment:
- SSH_AUTH_SOCK=/ssh-agent
```

You may have to change the `1000:1000` to the user and group IDs of your laptop. You may also have to change the `version` parameter to match the version of the `docker-compose.yml` file.

Adapting the above `docker-compose.override.yml` for MacOS should be relatively straight-forward. Windows users, I'm afraid you're on your own. If you figure this out, a PR documenting how to do it would be most welcome.

The above doesn't allow you to run the system tests. To keep the image small, it doesn't include Chrome or any other browser.

There is an experimental `docker-compose-system-test.yml` file, that runs the `bootstrap_forms` docker container along with an off-the-shelf Selenium container. To start this configuration:

```bash
RUBY_VERSION=3.2 docker-compose -f docker-compose-system-test.yml -f docker-compose.override.yml up&
RUBY_VERSION=3.2 docker-compose -f docker-compose-system-test.yml -f docker-compose.override.yml exec shell /bin/bash
```

(Sometimes, on shutdown, the Rails server PID file isn't removed, and so the above will fail. `rm demo/tmp/pids/server.pid` will fix it.)

Once in the shell:

```bash
cd demo
bundle exec rails test:system
```

Note that this system test approach is highly experimental and has some rough edges. The docker compose file and/or steps to run system tests may change. The tests currently fail, because the files with which they're being compared were generated on a Mac, but the Docker containers are running Linux.

#### Simple Dockerfile

This repository includes a `Dockerfile` to build an image with the minimum `bootstrap_form`-supported Ruby environment. To build the image:

```bash
docker build --tag bootstrap_form .
```

This builds an image called `bootstrap_form`. You can change that to any tag you wish. Just make sure you use the same tag name in the `docker run` command.

If you want to use a different Ruby version, or a smaller Linux distribution (although the distro may be missing tools you need):

```bash
docker build --build-arg "RUBY_VERSION=3.0" --build-arg "DISTRO=slim-buster" --tag bootstrap_form .
```

Then run the container you built with the shell, and create the bundle:

```bash
docker run --volume "$PWD:/app" --user $UID:`grep ^$USERNAME /etc/passwd | cut -d: -f4` -it bootstrap_form /bin/bash
bundle install
```

You can run tests in the container as normal, with `rake test`.

(Some of that command line is need for Linux hosts, to run the container as the current user.)

One of the disadvantages of this approach is that you can't release the gem from here, because the Docker container doesn't have access to your SSH credentials, or the right user name, or perhaps other things needed to release a gem. But for simple testing, it works.

#### Troubleshooting Docker

- With the above configuration, the gems are kept in `vendor/bundle` on your hosts, which is `$GEM_HOME` or `/app/vendor/bundle` in the running Docker container. If you're having permission problems when switching versions of Ruby or Rails, you can try `sudo rm -rf vendor/bundle` on the host, then run `BUNDLE_GEMFILES=gemfiles/7.0.gemfile bundle update` in the Docker container to re-install all the gems with the right permissions.
If you're intested in trying the Docker approach, read the [documentation](DOCKER.md).

### The Demo Application

Expand Down
75 changes: 75 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Working With Docker

This repository offers experimental support support for developing using Docker, if you're interested. Docker is _not_ required to work on this gem.

The `docker compose` approach should link to enough of your networking configuration that you can release the gem.
However, you have to do some of the configuration yourself, because it's dependent on your host operating system.

## Set-Up

Put your personal and OS-specific configuration in a `compose.override.yml` file.

The following instructions work for an Ubuntu host, and will probably work for other common Linux distributions. Add a `compose.override.yml` in the local directory, that looks like this:

```compose.override.yml
version: '3.3'
# https://blog.giovannidemizio.eu/2021/05/24/how-to-set-user-and-group-in-docker compose/
services:
shell:
# You have to set the user and group for this process, because you're going to be
# creating all kinds of files from inside the container, that need to persist
# outside the container.
# Change `1000:1000` to the user and default group of your laptop user.
user: 1000:1000
volumes:
- /etc/passwd:/etc/passwd:ro
- ~/.gem/credentials:/app/.gem/credentials:ro
# $HOME here is your host computer's `~`, e.g. `/home/reid`.
# `ssh` explicitly looks for its config in the home directory from `/etc/passwd`,
# so the target for this has to look like your home directory on the host.
- ~/.ssh:${HOME}/.ssh:ro
- ${SSH_AUTH_SOCK}:/ssh-agent
environment:
- SSH_AUTH_SOCK=/ssh-agent
```

You may have to change the `1000:1000` to the user and group IDs of your laptop. You may also have to change the `version` parameter to match the version of the `docker compose.yml` file.

Adapting the above `compose.override.yml` for MacOS should be relatively straight-forward. Windows users, I'm afraid you're on your own. If you figure this out, a PR documenting how to do it would be most welcome.

## Running

Start the containers:

```bash
docker compose up -d
```

You may need to install or update the gems:

```bash
docker compose exec -it shell bundle install
```

To get a shell in the container:

```bash
docker compose exec -it shell /bin/bash
```

Once in the shell:

```bash
cd demo
bundle exec rails test:system
```

Note that this system test approach is highly experimental and has some rough edges. The docker compose file and/or steps to run system tests may change. The tests currently fail, because the files with which they're being compared were generated on a Mac, but the Docker containers are running Linux.

## Troubleshooting Docker

- With the above configuration, the gems are kept in `vendor/bundle` on your hosts, which is `$GEM_HOME` or `/app/vendor/bundle` in the running Docker container. If you're having permission problems when switching versions of Ruby or Rails, you can try `sudo rm -rf vendor/bundle` on the host, then run `BUNDLE_GEMFILES=gemfiles/7.0.gemfile bundle update` in the Docker container to re-install all the gems with the right permissions.
- Sometimes, on shutdown, the Rails server PID file isn't removed, and so the above will fail. `rm demo/tmp/pids/server.pid` will fix it.

22 changes: 0 additions & 22 deletions Dockerfile

This file was deleted.

24 changes: 6 additions & 18 deletions docker-compose-system-test.yml → compose.yml
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
version: '3.3'

# Set up the Selenium container based on the Selenium official:
# https://github.com/SeleniumHQ/docker-selenium/blob/trunk/docker-compose-v3.yml
# And:
# https://medium.com/@retrorubies/chrome-as-a-service-for-rails-testing-b1a45e70fec1
services:
app: &app
build:
context: .
args:
NODE_MAJOR: "12"
YARN_VERSION: "1.22.4"
RUBY_VERSION: ${RUBY_VERSION}
image: bootstrap-form:latest-$RUBY_VERSION
tmpfs:
- /tmp

shell:
<<: *app
image: lenchoreyes/jade:rails-app-3.0-sqlite-bullseye
stdin_open: true
tty: true
volumes:
- .:/app:cached
environment:
- SSH_AUTH_SOCK=/ssh-agent
- NODE_ENV=development
- BOOTSNAP_CACHE_DIR=/usr/local/bundle/_bootsnap
- WEB_CONCURRENCY=1
- HISTFILE=/app/.bash_history
- SELENIUM_HOST=selenium
- SELENIUM_PORT=4444
- TEST_APP_HOST=shell
- TEST_APP_PORT=3001
ports:
- "3000:3000"
- "3001:3001"
command: /bin/bash

Expand Down
Loading

0 comments on commit 34e9120

Please sign in to comment.