buncha fixes to make sure env vars are set properly before creating the image, and move npm install to dockerfile to bake it in the image

This commit is contained in:
Silas 2023-07-28 18:10:37 -04:00
parent 221f800c15
commit 0e690663fe
Signed by: silentsilas
GPG Key ID: 4199EFB7DAA34349
8 changed files with 89 additions and 63 deletions

0
.dockerizedroot Normal file
View File

5
.env
View File

@ -1,3 +1,6 @@
CONTAINER_NAME=react-native-dockerized CONTAINER_NAME=react-native-dockerized
RN_PROJECT_FOLDER_NAME=app RN_PROJECT_FOLDER_NAME=app
SSH_KEY="~/.ssh/id_docker_dev" SSH_KEY="id_docker_dev"
NPM_TOKEN=
GH_TOKEN=
NODE_VERSION=16.13.0

View File

@ -3,20 +3,29 @@ FROM reactnativecommunity/react-native-android
# config and update # config and update
ENV DEBIAN_FRONTEND noninteractive ENV DEBIAN_FRONTEND noninteractive
ENV DOCKER=true
WORKDIR /home WORKDIR /home
RUN apt-get update RUN apt-get update
RUN mkdir /var/log/app RUN mkdir /var/log/app
ARG SSH_KEY ARG SSH_KEY
ARG NODE_VERSION
ARG GH_TOKEN
ARG NPM_TOKEN
ARG RN_PROJECT_FOLDER_NAME
# set up NVM and use v16 LTS # set up NVM and use v16 LTS
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
ENV NVM_DIR /root/.nvm ENV NVM_DIR /root/.nvm
ENV NODE_VERSION 16.13.0
RUN . "$NVM_DIR/nvm.sh" && nvm install $NODE_VERSION && nvm alias default $NODE_VERSION && nvm use default RUN . "$NVM_DIR/nvm.sh" && nvm install $NODE_VERSION && nvm alias default $NODE_VERSION && nvm use default
ENV NODE_PATH $NVM_DIR/versions/node/v$NODE_VERSION/lib/node_modules ENV NODE_PATH $NVM_DIR/versions/node/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
RUN npm install -g react-native-cli RUN npm install -g react-native-cli
# add gh/npm tokens and install project dependencies
RUN echo \"//github.com/:_authToken=$GH_TOKEN\" > /home/app/.npmrc
RUN echo \"//registry.npmjs.org/:_authToken=$NPM_TOKEN\" >> /home/app/.npmrc
RUN cd /home/$RN_PROJECT_FOLDER_NAME && npm install
# Install SSH server # Install SSH server
RUN apt-get -y install openssh-server RUN apt-get -y install openssh-server
COPY sshd_config /etc/ssh/sshd_config COPY sshd_config /etc/ssh/sshd_config
@ -31,4 +40,4 @@ COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY entrypoint.sh /entrypoint.sh COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"] CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

View File

@ -15,6 +15,7 @@ Things to keep in mind:
* [Docker Desktop ](https://docs.docker.com/desktop/install/mac-install/) * [Docker Desktop ](https://docs.docker.com/desktop/install/mac-install/)
* [OrbStack](https://orbstack.dev/) _(great alternative but it will be out of its free beta soon and may not be stable)_ * [OrbStack](https://orbstack.dev/) _(great alternative but it will be out of its free beta soon and may not be stable)_
* If you're running Linux, you can also just use the docker CLI and docker service, installed through your package manager. * If you're running Linux, you can also just use the docker CLI and docker service, installed through your package manager.
* A Github and NPM account
* A React Native project to dockerize! * A React Native project to dockerize!
## Installation ## Installation
@ -26,6 +27,8 @@ You will either want to dockerize an app you haven't cloned/created yet, or an e
<details> <details>
<summary>Expand</summary> <summary>Expand</summary>
&NewLine;
Depending on whether you're starting a new project or dockerizing an existing one, there are two options: Depending on whether you're starting a new project or dockerizing an existing one, there are two options:
```zsh ```zsh
@ -42,6 +45,8 @@ git clone git@github.com:my-github-org/my-rn-project.git app
<details> <details>
<summary>Expand</summary> <summary>Expand</summary>
&NewLine;
To dockerize an existing React Native repository, clone this repository first. Then, move your React Native repository into this repository under a folder named app. To dockerize an existing React Native repository, clone this repository first. Then, move your React Native repository into this repository under a folder named app.
```zsh ```zsh
@ -53,11 +58,36 @@ cd my-rn-project-dockerized && rm -rf .git
</details> </details>
#### Add `dockman.sh` to your PATH #### Configure Github and NPM Auth
<details> <details>
<summary>Expand</summary> <summary>Expand</summary>
&NewLine;
Prior to starting up the container, the image will run `npm install` during the build process. This may require Github authentication if you're installing NPM packages from private Github repositories.
#### Github
1. Create a [legacy access token](https://github.com/settings/tokens) with all Repo-related permissions checked, and save the token in your password manager.
2. Add `export GH_TOKEN="your_legacy_access_token"` to your `~/.zshrc` file
* Alternatively, you could add it to the `.env` file
#### NPM
1. If you're using private npm packages, create an [access token](https://docs.npmjs.com/creating-and-viewing-access-tokens) on npm's website. Ensure it has the appropriate permissions for the packages you need.
2. Add `export NPM_TOKEN="your_npm_access_token"` to your `~/.zshrc` file
* Alternatively, you could add it to the `.env` file
</details>
#### Add `dockman.sh` to your PATH
<details>
<summary>Expand - optional</summary>
&NewLine;
If you would like to run `dockman.sh` from any directory on your system, follow these steps: If you would like to run `dockman.sh` from any directory on your system, follow these steps:
1. Create a new directory named `.react-native-dockerized` in your home directory (if it doesn't already exist): 1. Create a new directory named `.react-native-dockerized` in your home directory (if it doesn't already exist):
@ -65,9 +95,9 @@ If you would like to run `dockman.sh` from any directory on your system, follow
mkdir -p $HOME/.react-native-dockerized mkdir -p $HOME/.react-native-dockerized
``` ```
2. Move the `dockman.sh` script into this new directory: 2. Copy the `dockman.sh` script into this new directory:
```zsh ```zsh
mv /path/to/dockman.sh $HOME/.react-native-dockerized cp ./dockman.sh $HOME/.react-native-dockerized
``` ```
3. Make the script executable: 3. Make the script executable:
@ -95,16 +125,12 @@ Note: The `source` command makes the changes effective immediately. You may need
</details> </details>
&NewLine;
Check out the other optional setup sections, especially [Configure Github Auth](#configure-github-auth) if your project has dependencies installing from a private Github repository.
## Usage ## Usage
After completing [Installation](#installation) and any optional setup: After completing [Installation](#installation) and any optional setup:
```zsh ```zsh
docker-compose up ./dockman.sh up
./dockman.sh start-metro ./dockman.sh start-metro
# boot up an Android emulator before this step # boot up an Android emulator before this step
./dockman.sh run-android ./dockman.sh run-android
@ -128,36 +154,29 @@ _You may need to run `sudo chmod +x ./dockman.sh` first for executable permissio
## Settings ## Settings
You can adjust a few settings in the `.env` file at the root of the repository. You can adjust a few settings in the `.env` file at the root of the repository. Alternatively you could add them to your shell's environment.
| Variable | Description | Default | | Variable | Description | Default |
| ------------- | ------------- | ------------- | | ------------- | ------------- | ------------- |
| `CONTAINER_NAME` | The name of the Docker container with which the script interacts. | `react-native-dockerized` | | `CONTAINER_NAME` | The name of the Docker container with which the script interacts. | `react-native-dockerized` |
| `SSH_KEY` | The location of the SSH key file used for secure communication with the Docker container. | `~/.ssh/id_docker_dev` | | `SSH_KEY` | The location of the SSH key file used for secure communication with the Docker container. | `~/.ssh/id_docker_dev` |
| `RN_PROJECT_FOLDER_NAME` | The name of the React Native project folder. This should match the name of the folder that you cloned at the root of your repository. | `app` | | `RN_PROJECT_FOLDER_NAME` | The name of the React Native project folder. This should match the name of the folder that you cloned at the root of this repository. | `app` |
| `NODE_VERSION` | The version of Node.js that will be installed by the Node Version Manager (NVM). | `16.13.0` |
| `NPM_TOKEN` | Token for authenticating with npm for installing npm packages. This should be a valid token associated with your npm account. | - |
| `GH_TOKEN` | Token for authenticating with GitHub. This is required for installing packages from private GitHub repositories. | - |
If you plan on running multiple Docker containers simultaneously, you will need to assign a unique name to each container. For instance, if you're developing two separate React Native apps, you'll need to dockerize the second app using a different container name. If you plan on running multiple Docker containers simultaneously, you will need to assign a unique name to each container. For instance, if you're developing two separate React Native apps, you'll need to dockerize the second app using a different container name.
Please note that modifying the `RN_PROJECT_FOLDER_NAME` variable won't rename the project folder on your host machine. This variable should match the existing name of your project folder. Please note that modifying the `RN_PROJECT_FOLDER_NAME` variable won't rename the project folder on your host machine. This variable should match the existing name of your project folder.
### Configure Github Auth
<details>
<summary>Expand - optional, but highly recommended</summary>
Prior to starting up the container, the image will run `npm install` during the build process. This may require Github authentication if you're installing NPM packages from private Github repositories.
1. Create a [legacy access token](https://github.com/settings/tokens) with all Repo-related permissions checked, and save the token in your password manager.
2. Add `export GH_TOKEN="your_legacy_access_token"` to your `~/.zshrc` file
* Alternatively, you could add it to the `.env` file
</details>
### Remote Workspace Inside The Container: ### Remote Workspace Inside The Container:
<details> <details>
<summary>Expand - optional</summary> <summary>Expand - optional</summary>
&NewLine;
You can open a new remote workspace in your IDE to access the React Native project within this Docker container. With VS Code, you may not require SSH for this, thanks to the robust integration of the [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) extension with Docker. However, if you're using VSCodium, your best bet is the [Open Remote SSH](https://open-vsx.org/vscode/item?itemName=jeanp413.open-remote-ssh) extension. You can open a new remote workspace in your IDE to access the React Native project within this Docker container. With VS Code, you may not require SSH for this, thanks to the robust integration of the [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) extension with Docker. However, if you're using VSCodium, your best bet is the [Open Remote SSH](https://open-vsx.org/vscode/item?itemName=jeanp413.open-remote-ssh) extension.
Do note that VSCodium comes with certain limitations, such as the need to manually provision an SSH server and client - but hey that's the FOSS life. Do note that VSCodium comes with certain limitations, such as the need to manually provision an SSH server and client - but hey that's the FOSS life.

View File

@ -9,6 +9,11 @@ services:
- SSH_KEY=${SSH_KEY} - SSH_KEY=${SSH_KEY}
- RN_PROJECT_FOLDER_NAME=${RN_PROJECT_FOLDER_NAME} - RN_PROJECT_FOLDER_NAME=${RN_PROJECT_FOLDER_NAME}
- GH_TOKEN=${GH_TOKEN} - GH_TOKEN=${GH_TOKEN}
- NPM_TOKEN=${NPM_TOKEN}
- NODE_VERSION=${NODE_VERSION}
environment:
- GH_TOKEN=${GH_TOKEN}
- NPM_TOKEN=${NPM_TOKEN}
container_name: "${CONTAINER_NAME}" container_name: "${CONTAINER_NAME}"
volumes: volumes:
- type: bind - type: bind
@ -16,6 +21,3 @@ services:
target: /home/app target: /home/app
ports: ports:
- 8081:8081 - 8081:8081
environment:
- EXPO_DEVTOOLS_LISTEN_ADDRESS=0.0.0.0

View File

@ -22,10 +22,24 @@ if [[ -z "${CONTAINER_NAME}" ]]; then
fi fi
# Define the project directory # Define the project directory
PROJECT_DIR="/home/app" PROJECT_DIR="/home/$RN_PROJECT_FOLDER_NAME"
# Docker command handling # Docker command handling
case $1 in case $1 in
up)
# List of required environment variables
REQUIRED_VARS=("SSH_KEY" "GH_TOKEN" "NPM_TOKEN" "NODE_VERSION" "RN_PROJECT_FOLDER_NAME" "CONTAINER_NAME")
for VAR in ${REQUIRED_VARS[@]}; do
if [[ -z "${!VAR}" ]]; then
echo "Error: Required environment variable $VAR is not set"
exit 1
fi
done
# If we get here, all variables are set
docker-compose up
;;
stop-metro) stop-metro)
docker exec -it ${CONTAINER_NAME} supervisorctl stop npm docker exec -it ${CONTAINER_NAME} supervisorctl stop npm
;; ;;
@ -35,15 +49,14 @@ case $1 in
echo "Please set the RN_PROJECT_FOLDER_NAME environment variable before running the script." echo "Please set the RN_PROJECT_FOLDER_NAME environment variable before running the script."
exit 1 exit 1
fi fi
docker exec ${CONTAINER_NAME} /bin/bash -c "echo \"//github.com/:_authToken=$GH_TOKEN\" > ${PROJECT_DIR}/.npmrc"
docker exec ${CONTAINER_NAME} /bin/bash -c "cd ${PROJECT_DIR} && npm install" || { echo 'npm install failed' ; exit 1; } docker exec ${CONTAINER_NAME} /bin/bash -c "cd ${PROJECT_DIR} && npm install" || { echo 'npm install failed' ; exit 1; }
docker exec ${CONTAINER_NAME} /bin/bash -c "rm -f ${PROJECT_DIR}/.npmrc" docker exec ${CONTAINER_NAME} supervisorctl start npm
docker exec ${CONTAINER_NAME} supervisorctl start npm -- --reset-cache
docker logs -f ${CONTAINER_NAME} docker logs -f ${CONTAINER_NAME}
;; ;;
metro-logs) metro-logs)
docker exec -it ${CONTAINER_NAME} cat /var/log/app/npm.log echo "Press CTRL + C to safely exit. It won't stop the server."
docker exec -it ${CONTAINER_NAME} supervisorctl tail -f npm stdout
;; ;;
connect-android) connect-android)
@ -72,13 +85,14 @@ case $1 in
echo "Please set the SSH_KEY environment variable before running the script." echo "Please set the SSH_KEY environment variable before running the script."
exit 1 exit 1
fi fi
SSH_KEY_PATH="$HOME/.ssh/id_docker_dev"
# generate ssh key # generate ssh key
if [ ! -f "${SSH_KEY}" ]; then if [ ! -f "${SSH_KEY_PATH}" ]; then
ssh-keygen -t ed25519 -f "${SSH_KEY}" -N "" ssh-keygen -t ed25519 -f ${SSH_KEY_PATH} -N ""
echo "SSH key generated at ${SSH_KEY}" echo "SSH key generated at ${SSH_KEY_PATH}"
else else
echo "SSH key already exists at ${SSH_KEY}" echo "SSH key already exists at ${SSH_KEY_PATH}"
fi fi
# Check if Docker is running # Check if Docker is running
@ -102,7 +116,7 @@ case $1 in
echo "SSH config already contains the Docker IP." echo "SSH config already contains the Docker IP."
else else
echo "Adding Docker IP to SSH config..." echo "Adding Docker IP to SSH config..."
echo -e "Host ${CONTAINER_IP}\n\tPort 22\n\tUser root\n\tPubkeyAuthentication yes\n\tIdentityFile ${SSH_KEY}" >> ~/.ssh/config echo -e "Host ${CONTAINER_IP}\n\tPort 22\n\tUser root\n\tPubkeyAuthentication yes\n\tIdentityFile ${SSH_KEY_PATH}" >> ~/.ssh/config
echo "Docker IP added to SSH config." echo "Docker IP added to SSH config."
fi fi
;; ;;

View File

@ -1,21 +0,0 @@
#!/bin/bash
set -e
# Check if GH_TOKEN exists
if [[ -n $GH_TOKEN ]]; then
# Github auth for private npm packages
su -c "echo \"//github.com/:_authToken=$GH_TOKEN\" > /home/app/.npmrc"
fi
# install npm dependencies
su -c "cd /home/app && npm install"
# If GH_TOKEN exists, remove the token
if [[ -n $GH_TOKEN ]]; then
su -c "rm -f /home/app/.npmrc"
fi
# run supervisord
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf

View File

@ -19,10 +19,10 @@ stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log stderr_logfile=/var/log/supervisor/%(program_name)s.log
[program:npm] [program:npm]
command=bash -c "npm start -- --reset-cache --docker" command=npm start -- --reset-cache
user=root user=root
autostart=false autostart=true
autorestart=false autorestart=true
directory=/home/app directory=/home/app
stdout_logfile=/var/log/app/%(program_name)s.log stdout_logfile=/var/log/app/%(program_name)s.log
stderr_logfile=/var/log/app/%(program_name)s.log stderr_logfile=/var/log/app/%(program_name)s.log