Sony Arouje

a programmer's log

Expo react-native development in Docker

with 7 comments

I spent most of my free time learning developing applications in different platforms. Recently I was spending time in Expo, a platform to build react-native apps. Expo is a pretty good platform to kick start your react native development. One of the difficulty I always face is upgrading the versions, for e.g. some times expo releases multiple updates in a month. When upgrading in my Windows machine, there could be issues, either a file lock or some thing else. These installations issues leads to frustrations and fire fighting to return to a working state. Recently my friend Sendhil told me, how he use VS Code to remote develop using containers. I decided to take a look at it.

I kept myself away from docker for some time. Decided to try out docker again. It took me few mins to up and running a docker image maintained by node. Next step was to install the expo-cli and other dependencies to run my expo test application. I had to over come several errors popped up when running expo code in a container. Spend hours reading forums and posts to resolve it one by one. Here is the Dockerfile I came up, which can be used to develop any expo based applications.

The below workflow holds good for any kind of node or react or react-native, etc developments.

Dockerfile

FROM node:10.16-buster-slim
LABEL version=1.0.0

ENV USERNAME dev
RUN useradd -rm -d /home/dev -s /bin/bash -g root -G sudo -u 1005 ${USERNAME}

EXPOSE 19000
EXPOSE 19001
EXPOSE 19002

RUN apt update && apt install -y \
    git \
    procps

#used by react native builder to set the ip address, other wise 
#will use the ip address of the docker container.
ENV REACT_NATIVE_PACKAGER_HOSTNAME="10.0.0.2"

COPY *.sh /
RUN chmod +x /entrypoint.sh \
    && chmod +x /get-source.sh

#https://github.com/nodejs/docker-node/issues/479#issuecomment-319446283
#should not install any global npm packages as root, a new user 
#is created and used here
USER $USERNAME

#set the npm global location for dev user
ENV NPM_CONFIG_PREFIX="/home/$USERNAME/.npm-global"

RUN mkdir -p ~/src \
    && mkdir ~/.npm-global \
    && npm install expo-cli --global

#append the .npm-global to path, other wise globally installed packages 
#will not be available in bash
ENV PATH="/home/$USERNAME/.npm-global:/home/$USERNAME/.npm-global/bin:${PATH}"

ENTRYPOINT ["/entrypoint.sh"]
CMD ["--gitRepo","NOTSET","--pat","NOTSET"]

 

VS Code to develop inside a container

To enable VS Code to develop inside a container, we need to Install Remote Development Extension pack. Here is the more detailed write up from MS

To enable remote development we need two more files in our source folder.

  • docker-compose.yml
  • devcontainer.json

docker-compose.yml

version: '3.7'

services:
  testexpo:
    environment:
      - REACT_NATIVE_PACKAGER_HOSTNAME=10.0.0.2
    image: sonyarouje/expo-buster:latest
    extra_hosts:
      - "devserver:10.0.0.2"
    command: "--gitRepo sarouje.visualstudio.com/_git/expotest --pat z66cu5tlfasa7mbiqwrjpskia"
    expose:
      - "19000"
      - "19001"
      - "19002"
    ports:
      - "19000:19000"
      - "19001:19001"
      - "19002:19002"
    volumes:
      - myexpo:/home/node/src
volumes:
  myexpo:

 

  • REACT_NATIVE_PACKAGER_HOSTNAME: Will tell react-native builder to use the configured ip when exposing the bundler, else will use the docker container’s ip and will not be able to access from your phone.
  • command: Specify your git repo to get the source code and the pat code. When running docker-compose up, docker container will use these details to clone your repo to /home/dev/src directory of the container.
  • volumes: Containers are short lived and stopping the container will loose you data. For e.g. once the container is up we might install npm packages. If the packages are not able to persist then we need to reinstall packages every time we start the container. In order to persist the packages and changes, docker-compose creates a named volume and keep the files of /home/dev/src in the volume and can be accessible even after docker restart.

Keep in mind ‘docker-compose down’ will remove the volume and we need to reinstall all the packages again.

devcontainer.json

Create a new folder named .devcontainer and inside the new folder create a file named devcontainer.json. Below is the structure of the file.

{
    "name": "expo-test",
    "dockerComposeFile": "../docker-compose.yml",
    "service": "testexpo",
    "workspaceFolder": "/home/dev/src/expotest",
	"extensions": [
       "esbenp.prettier-vscode"
    ]
    "shutdownAction": "stopCompose"
}
  • dockerComposeFile: will tell where to find the docker-compose.yml file
  • service: Service configured in docker-compose.yml file
  • workspaceFolder: Once VS Code attached to the container, will open this workspace folder.

    extensions: Mention what all the extensions need to be installed in VS Code running from the container.

Work flow

  • Download the latest version of docker
  • Open powershell/command prompt and run ‘docker pull sonyarouje/expo-buster’
  • Open your source folder and create docker-compose.yml and .devcontainer/devcontainer.json file
  • Modify docker-compose.yml and give the git repo and pat, etc
  • Open VS Code in source folder. VS Code will prompt to Reopen in Container, click Reopen in Container button. Wait for some time, and VS Code will launch from the container.
  • Once launched in container, all your code changes will be available only in the container. Make sure to push your changes to git before exiting the container.

Advantages of containerized approach

We can spawn a new container at ease and test our code against any new version of libraries we are using. We don’t need to put our dev machine at risk. Any break or compilation issues, we can always destroy the container and go back to the dev container and proceed with our development. No need to restore our dev machine to a working state. If the upgrade succeed then we can always destroy the current dev container and use the new container as the development container. No more hacking with our current working container.

Where is the source?

 

All the dockerfiles and scripts are pushed to git. Feel free to fork it or give me a pull request in case of any changes. I created two versions of docker file, one for alpine and one for buster. As of now stable VS Code release wont support alpine but you can always switched to VSCode insider build to use alpine.

Docker image is published to docker hub, can be pulled using sonyarouje/expo-buster or sonyarouje/expo-buster:3.0.6. Here 3.0.6 is the version of expo-cli.

 

Written by Sony Arouje

August 2, 2019 at 7:18 pm

Posted in .NET

7 Responses

Subscribe to comments with RSS.

  1. Great tutorial, thank you so much. I really appreciated that.

    Anonymous

    January 8, 2020 at 7:51 am

  2. Dude, I’m working with your script and having some issues once I’m logged into the container. Trying to do some work inside but am unable to do anything requiring root level privileges. The user dev doesn’t have the required privileges and thus I have tried adding a password to the account during creation using the -p flag but still it fails. Any thoughts?

    icarlosmendez

    July 24, 2020 at 4:36 am

    • I dont know what you are trying inside the container with root privilege. Till now the container is working good for me without any changes to the container.

      Sony Arouje

      August 3, 2020 at 10:24 am

  3. This is a great way to work, however with expo I find a problem. This is since when you run expo start you would like to open the simulator (iOS) running on the host machine. This is where things get complicated unfortunately

    Anonymous

    September 30, 2021 at 12:35 am

  4. Thank you for your tutorial. It is really clean and nice to work that way. The main problem I find is that when you want to run a simulator after running ‘expo start’ is a problem, I would like to have the simulator (iOS) running on the host mac machine.
    did you manage to find a solution for it?

    Elic

    September 30, 2021 at 12:38 am


Leave a comment