Dev Container for React Native with Expo

Aniello Musella - Sep 22 '23 - - Dev Community

In this post, I'll show how to create a Development container (aka dev container) to use it to develop a React Native app with Expo.

What should you know?

  • Basic knowledge of Docker
  • Basic knowledge of React Native
  • Basic knowledge of Expo
  • Basic knowledge of Bash

What do you need?

Why dev containers?

In short:

  • You prepare the dev environment one time and every developer can use it.
  • Dev containers are always ready when you need it.
  • Dev containers are always consistent for every developer.
  • Dev containers are fully integrated with popular IDE like Visual Studio Code, PyCharm and others.
  • You can use them remotely

If you want to go into the details, check the following link from @blackgirlbytes Why are people developing inside containers?

Dev Container preparation

Let's prepare the working directory:

animus@devto:~$ mkdir my-app
animus@devto:~$ cd my-app
animus@devto:~$ git init -b main
Enter fullscreen mode Exit fullscreen mode

Start Visual Studio Code:

animus@devto:~$ code .
Enter fullscreen mode Exit fullscreen mode

Type CTRL+SHIFT+P to run the Command Palette and when ready type Dev Containers: Add Dev Container configuration files

Image description

Choose the dev container Node.js & TypeScript container like shown below.

Image description

Choose default image and don't select any features.

After saved the dev container configuration, you should see a folder named ./devcontainer with a JSON file devcontainer.json containing the default definition of the container.

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
    "name": "Node.js & TypeScript",
    // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
    "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye"

    // 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": [],

    // Use 'postCreateCommand' to run commands after the container is created.
    // "postCreateCommand": "yarn install",

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

    // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
    // "remoteUser": "root"
}
Enter fullscreen mode Exit fullscreen mode

Edit this file like shown below:

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
    "name": "Node.js & TypeScript",
    // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
    "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",

    // 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": [8081],
    "initializeCommand": "bash .devcontainer/initializeCommand.sh",
    // Use 'postCreateCommand' to run commands after the container is created.
    "postCreateCommand": "bash .devcontainer/postCreateCommand.sh",

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

    // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
    // "remoteUser": "root",

    "runArgs": ["-p=8081:8081", "--env-file", ".devcontainer/.env"]

}

Enter fullscreen mode Exit fullscreen mode

In this new version of this file, I've added:

  • initializeCommand This section permit to execute a command before the build of the container. I've used this command to execute a script to generate a file of environment variables to use them in the container (the script will be described in the next chapter).
  bash .devcontainer/initializeCommand.sh
Enter fullscreen mode Exit fullscreen mode
  • postCreateCommand This section permit to execute a command after the build of the container. I've used this command to execute a script to install Expo and other dependencies like watchman
  bash .devcontainer/postCreateCommand.sh
Enter fullscreen mode Exit fullscreen mode
  • forwardPorts I've exposed the port number 8081 to permit the Expo client to access to your app.
  "forwardPorts": [8081]
Enter fullscreen mode Exit fullscreen mode
  • runArgs I've defined an argument to run the container:
    • port binding with the host
    • environment file (generated in the initialize command script)
    "runArgs": ["-p=8081:8081", "--env-file", ".devcontainer/.env"]
Enter fullscreen mode Exit fullscreen mode

The initialize command script

The initialize command script initializeCommand.sh located in ./devcontainer folder has the goal to gather your IP address (the script is inspired by this one). The address is set in an environment variable named REACT_NATIVE_PACKAGER_HOSTNAME used by Expo to expose the app.
This variable will'be printed in the file named .env located in the same directory of the script.

The content of the script:

#!/bin/bash
echo "Gathering you ip for dev container"

##############################################################################################
# en (Ethernet) - ib (InfiniBand) - sl (Serial line IP (slip)) - wl (Wireless local area 
network (WLAN)) - ww (Wireless wide area network (WWAN))
#############################################################################################
your_interface_name="eno" 
interface_prefix="en" # Choose the interface network.
iname=$(ip -o link show | sed -rn '/^[0-9]+: en/{s/.: ([^:]*):.*/\1/p}')
ip=`ifconfig $iname  | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | sed 's/inet //g'`

echo "REACT_NATIVE_PACKAGER_HOSTNAME=$ip" > .devcontainer/.env

Enter fullscreen mode Exit fullscreen mode

The content of the .env file:

REACT_NATIVE_PACKAGER_HOSTNAME=192.168.0.72
Enter fullscreen mode Exit fullscreen mode

The post create command script

The post create command script postCreateCommand.sh located in ./devcontainer folder has the goal to set up Expo and watchman as described in the Expo guide.

The content of the script:

echo -e "\nStarting post creat command script..."
echo "Dev machine:"
uname -a
echo -e "\nInstalling expo boiler plate..."
npm install --save-dev -y create-expo-app@2.1.1
echo -e "\nInstalling watchman...\n"
sudo apt update
sudo apt install watchman
watchman version

echo -e "\n*******************************"
echo -e "\nDev container ready!".
echo -e "\n*******************************\n"
Enter fullscreen mode Exit fullscreen mode

Create and run the Dev Container

Open the Command Palette (CTRL+SHIFT+P) and select Rebuild and Reopen in Container

Image description

Create the app

To create the app, open a terminal inside the dev container and run the following command:

animus@mydevcontainer:~$ npx create-expo-app -t blank myapp
Enter fullscreen mode Exit fullscreen mode

Run the app

To run the app, type the following command:

animus@mydevcontainer:~$ cd myapp
animus@mydevcontainer:~$ npx expo start
Enter fullscreen mode Exit fullscreen mode

You'll see something like this:

Image description

Scan the barcode with the Expo Client App (from your smartphone), and you'll see your app "myapp"!

Have a fun!

Conclusions

Dev containers are great when you want to prepare a dev environment fully replicable for you and for your team. The little effort that you put at the beginning is well paid off later. Dev containers are useful even in the mobile development using React Native with Expo improving the productivity of the team.

Suggestions and corrections are welcome.

. . . . . . . . . . . . . . .
Terabox Video Player