[DevContainer] Developing on Expo using VSCode and Docker
Developing multiplatform mobile apps in a portable dev environment
I am a productivity freak. I want my dev environments to be the best and most predictable, so that I can share them with my coworkers easily. You can read some of the posts around using VSCode and Docker based development environments I have written earlier on my blog ( blog.mandraketech.in ). In all the previous cases, I have been working with the server side, and hence NodeJS is the primary target.
I am also a fan of creating Remote Container based development environments. It allows me to:
- have multiple environments running without killing the CPU on my old Intel i3 processor
- allows me to run the Docker host on Digital Ocean / AWS EC2, and hence share environments with my peers
So, I started from scratch, building up on my experience with the NodeJS and VSCode based environments.
Let's create a directory for ourselves, and get started. The name of the directory should be a name that you would want to see in the Docker Desktop dashboard, and helps you identify what you are running. For example: hello-app-dev
You can find all the code from this post at https://github.com/navneetkarnani/vscode-expo-starter
Creating the Dockerfile
The first stage is to create a Docker image, that will have all the tools we want to run. In this case, we want an image that has ReactNative, Expo CLI, NodeJS, Typescript and ESLint preinstalled. So, I started with Node 16, and built this:
Create a file called Dockerfile
, with the below contents:
# [Choice] Node.js version: 16, 14, 12
FROM node:16
# init for VS Code
RUN mkdir -p /root/workspace /root/.vscode-server/extensions
# Install eslint typescript expo
RUN npm install -g npm@latest
RUN npm install -g eslint typescript expo-cli @expo/ngrok@^4.1.0
RUN node --version && npm --version
CMD /bin/sh -c "while sleep 86000; do :; done"
You will notice that I have @expo/ngrok
installed too. This is because we want to start expo in tunnel
mode directly from the commandline, instead of having to launch it in LAN mode and then switch. So, ignore it for now, you will see it in action later.
Creating the docker-compose file
docker compose
enables us to define a full environment, with the storage/volumes and any other customisations necessary. Since my intention is to build a fully remote enabled environment, we will store all our code in a docker volume. That way, there are no references to the host.
Create a file called docker-compose.yml
, with the contents below:
services:
expo-dev:
build:
dockerfile: ./Dockerfile
volumes:
- code:/root/workspace
volumes:
code: {}
with this, we are in a position to run the command:
docker compose up -d
to see the environment working. But we are not done yet. Hold on So make sure you clean it up: docker compose down --remove-orphans -v
Remote container on VS Code using DevContainer magic
Tough not mandatory reading, if you are interested in a detailed understanding of the VSCode feature, read up here: code.visualstudio.com/docs/remote/create-de..
Lets create a file called .devcontainer.json
, with the following contents:
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.191.0/containers/docker-existing-docker-compose
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
{
"name": "expo-dev",
"dockerComposeFile": [
"docker-compose.yml"
],
"service": "expo-dev",
"workspaceFolder": "/root/workspace",
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [ 19000, 19001, 19002 ],
}
For a more detailed configuration, with more pre-configuration, refer to the code in the [Git repo] (github.com/navneetkarnani/vscode-expo-starter)
One point I want to call out here though, the use of "forwardPorts" in devcontainer.json instead of the "ports" in docker-compose.yml
.
The purpose of ports
in the docker-compose.yml
is to bind a port to the host where the container is running. Whereas, the forwardPorts
mechanism uses the VS Code infrastructure to forward the traffic.
The difference is that the container is not locking the specified ports on the host. This allows multiple environments to run side-by-side. Plus, does not need opening firewall ports when using a remote Docker host.
Starting the container with VS Code
We are now ready to go. Make sure you have VS Code installed on your machine, and the Remote - Containers
extention installed. You can also search for ms-vscode-remote.remote-containers
extension.
Now, open the folder containing the above files in VS Code. Either from the terminal, by typing code .
or just opening the folder, as you would otherwise do.
VS Code will prompt you that it found a Dev Container configuration file
. Click on the Reopen in Container
.
Or, alternatively, you can start the Command Palette
using the F1
key, and search for Reopen in Container
. If you make changes to any of the above files, you can also do a Rebuild and reopen in Container
.
Getting started with Expo
As you may have noticed, the code
volume is mounted to the /root/workspace
folder. So, you need to open that folder in VS Code. Given the .devcontainer.json
file, it should be open by default.
Start the terminal, and make sure you are in the same folder.
We will generate a "starter" project, for testing, called hello
.
Run expo init hello
in the terminal. Select a template of your choice ( I prefer the typescript ones ). And wait for the process to complete.
Running Expo, the final leg
Before running the app, make sure you have the Expo Go
application installed on your development phone.
On the terminal, switch to the hello
folder, and run expo start --tunnel
. The browser will open up with the packager console, and the Tunnel
mode selected. If not, then something is not right. Message me and we will try to figure it out.
You will see a QR code in the terminal, as well as on the browser. Scan it, and it should open using Expo Go.
Summarizing
What did we achieve in this post:
With only docker cli as the local component on a machine, we are able to build a development environment for Expo. This environment can run on machines with Docker Desktop, or where the Docker host is running remote. Loads of options. This is even AWS Fargate friendly.
VS Code documentation on using [Remote Docker host] ( code.visualstudio.com/docs/remote/container.. )
[Digital Ocean Running remote Docker host] ( digitalocean.com/community/tutorials/how-to.. )
[AWS doc on running docker in EC2] ( docs.aws.amazon.com/AmazonECS/latest/develo.. )
This blog was originally published by Navneet Karnani ( navneet@mandraketech.in ) on his blog at: https://blog.mandraketech.in/developing-on-expo-with-ios-using-vscode-and-docker