|
| 1 | +--- |
| 2 | +title: "Making a dockitect Dockerfile into a Running Container" |
| 3 | +output: rmarkdown::html_vignette |
| 4 | +vignette: > |
| 5 | + %\VignetteIndexEntry{Making a dockitect Dockerfile into a Running Container} |
| 6 | + %\VignetteEngine{knitr::rmarkdown} |
| 7 | + %\VignetteEncoding{UTF-8} |
| 8 | +--- |
| 9 | + |
| 10 | +```{r, include = FALSE} |
| 11 | +knitr::opts_chunk$set( |
| 12 | + collapse = TRUE, |
| 13 | + comment = "#>" |
| 14 | +) |
| 15 | +
|
| 16 | +Sys.setenv(R_USER_CACHE_DIR = tempfile()) |
| 17 | +``` |
| 18 | + |
| 19 | +## Introduction |
| 20 | + |
| 21 | +After creating a Dockerfile with `dockitect`, the next steps involve building a |
| 22 | +Docker image and running it as a container. This vignette walks through this |
| 23 | +process with practical examples, assuming you have Docker installed on your system. |
| 24 | + |
| 25 | +If you haven't installed Docker yet, visit the [Docker installation page](https://docs.docker.com/get-docker/) for instructions specific to your |
| 26 | +operating system. |
| 27 | + |
| 28 | +## Building Your Docker Image |
| 29 | + |
| 30 | +Once you've generated a Dockerfile with `dockitect`, you'll need to build a |
| 31 | +Docker image from it. This is done by interacting with Docker on the |
| 32 | +command-line interface: |
| 33 | + |
| 34 | +```bash |
| 35 | +# Basic build command |
| 36 | +docker build -t my-r-project . |
| 37 | + |
| 38 | +# Build with a specific tag (e.g., for versioning) |
| 39 | +docker build -t my-r-project:1.0.0 . |
| 40 | + |
| 41 | +# Build with build arguments (if your Dockerfile uses ARG) |
| 42 | +docker build --build-arg R_VERSION=4.4.0 -t my-r-project . |
| 43 | +``` |
| 44 | + |
| 45 | +The `-t` option tags your image with a name, making it easier to reference later. |
| 46 | +The `.` at the end tells Docker to look for a `Dockerfile` in the current directory. |
| 47 | + |
| 48 | +During the build process, Docker will execute each instruction in your |
| 49 | +`Dockerfile` sequentially and create a series of intermediate layers. These |
| 50 | +layers are cached, which means subsequent builds can be much faster if parts |
| 51 | +of your `Dockerfile` haven't changed. |
| 52 | + |
| 53 | +:::{.callout-tip} |
| 54 | +Effective use of layer caching can significantly speed up your Docker image builds. |
| 55 | +::: |
| 56 | + |
| 57 | +## Running Containers Based on Your Image |
| 58 | + |
| 59 | +After building the image, you can run it as a container using various configurations: |
| 60 | + |
| 61 | +```bash |
| 62 | +# Basic run command |
| 63 | +docker run my-r-project |
| 64 | + |
| 65 | +# Run interactively with a shell |
| 66 | +docker run -it my-r-project bash |
| 67 | + |
| 68 | +# Run with environment variables |
| 69 | +docker run -e "DEBUG=TRUE" my-r-project |
| 70 | + |
| 71 | +# Run with a volume for data persistence |
| 72 | +docker run -v $(pwd)/data:/app/data my-r-project |
| 73 | + |
| 74 | +# Run a Shiny app with port mapping |
| 75 | +docker run -p 3838:3838 my-shiny-app |
| 76 | +``` |
| 77 | + |
| 78 | +Here's what these options do: |
| 79 | + |
| 80 | +- `-it`: Provides an interactive terminal |
| 81 | +- `-p 3838:3838`: Maps port 3838 from the container to port 3838 on your host |
| 82 | +- `-e "DEBUG=TRUE"`: Sets an environment variable inside the container |
| 83 | +- `-v $(pwd)/data:/app/data`: Mounts your local directory to a location in the container |
| 84 | + |
| 85 | +For Shiny apps and Plumber APIs, the `-p` flag is crucial as it maps a port |
| 86 | +from the container to your host machine, allowing you to access the web application. |
| 87 | + |
| 88 | +## Container Management |
| 89 | + |
| 90 | +Here are some useful commands for managing your Docker containers and images: |
| 91 | + |
| 92 | +```bash |
| 93 | +# List running containers |
| 94 | +docker ps |
| 95 | + |
| 96 | +# List all containers (including stopped ones) |
| 97 | +docker ps -a |
| 98 | + |
| 99 | +# Stop a running container |
| 100 | +docker stop <container_id> |
| 101 | + |
| 102 | +# Remove a container |
| 103 | +docker rm <container_id> |
| 104 | + |
| 105 | +# List images |
| 106 | +docker images |
| 107 | + |
| 108 | +# Remove an image |
| 109 | +docker rmi my-r-project |
| 110 | +``` |
| 111 | + |
| 112 | +You can refer to containers by either their ID (shown in `docker ps`) or by |
| 113 | +the name assigned when running them. If you don't specify a name with `--name` |
| 114 | +when starting a container, Docker assigns a random name. |
| 115 | + |
| 116 | +## Example Workflows |
| 117 | + |
| 118 | +### Complete Workflow for a Shiny App |
| 119 | + |
| 120 | +Let's walk through a complete workflow for containerizing a Shiny application: |
| 121 | + |
| 122 | +```{r} |
| 123 | +#| eval: false |
| 124 | +# 1. Generate the Dockerfile |
| 125 | +library(dockitect) |
| 126 | +dk_template_shiny( |
| 127 | + r_version = "4.4.0", |
| 128 | + port = 3838, |
| 129 | + app_dir = "shiny_app/" |
| 130 | +) |> |
| 131 | + write_dockerfile() |
| 132 | +``` |
| 133 | + |
| 134 | +Then, in your terminal: |
| 135 | + |
| 136 | +```bash |
| 137 | +# 2. Build the Docker image |
| 138 | +## Note: For ARM-based systems, use --platform linux/amd64. |
| 139 | +docker build --platform linux/amd64 -t my-shiny-app . |
| 140 | + |
| 141 | +# 3. Run the container |
| 142 | +docker run -p 3838:3838 my-shiny-app |
| 143 | +``` |
| 144 | + |
| 145 | +Now you can access your Shiny app by navigating to <http://localhost:3838/app> in your web browser. |
| 146 | + |
| 147 | +### Running an R Script with Volume Mounting |
| 148 | + |
| 149 | +For data analysis scripts, you often want to share data between your host and the container: |
| 150 | + |
| 151 | +```{r} |
| 152 | +#| eval: false |
| 153 | +# 1. Generate the Dockerfile |
| 154 | +library(dockitect) |
| 155 | +dk_from_script("analysis.R") |> |
| 156 | + write_dockerfile() |
| 157 | +``` |
| 158 | + |
| 159 | +Then, in your terminal: |
| 160 | + |
| 161 | +```bash |
| 162 | +# 2. Build the Docker image |
| 163 | +docker build -t my-analysis . |
| 164 | + |
| 165 | +# 3. Run with volume mounting for input/output |
| 166 | +docker run -v $(pwd)/data:/app/data -v $(pwd)/results:/app/results my-analysis |
| 167 | +``` |
| 168 | + |
| 169 | +This mounts your local `data` and `results` directories to the container, |
| 170 | +allowing your R script to read input data and write results that persist after |
| 171 | +the container exits. |
| 172 | + |
| 173 | +### Running an R Environment for Interactive Use |
| 174 | + |
| 175 | +For interactive data analysis, you might want a container with specific packages and dependencies: |
| 176 | + |
| 177 | +```{r} |
| 178 | +#| eval: false |
| 179 | +# 1. Generate a Dockerfile with your packages |
| 180 | +library(dockitect) |
| 181 | +dk_template_base( |
| 182 | + r_version = "4.4.3", |
| 183 | + additional_pkgs = c("visualize") |
| 184 | +) |> |
| 185 | + write_dockerfile() |
| 186 | +``` |
| 187 | + |
| 188 | +In your terminal: |
| 189 | + |
| 190 | +```bash |
| 191 | +# 2. Build the image |
| 192 | +docker build -t r-interactive . |
| 193 | + |
| 194 | +# 3. Run interactively with volume mount for your project files |
| 195 | +docker run -it -v $(pwd):/app r-interactive R |
| 196 | +``` |
| 197 | + |
| 198 | +This gives you an interactive R session with all your packages pre-installed, and your current directory mounted so you can access your files. |
| 199 | + |
| 200 | +## Troubleshooting Common Issues |
| 201 | + |
| 202 | +### Build Fails with Package Installation Errors |
| 203 | + |
| 204 | +If your build fails during package installation, it might be due to missing |
| 205 | +system dependencies. The `dk_add_sysreqs()` function in `dockitect` can help |
| 206 | +with this: |
| 207 | + |
| 208 | +```{r} |
| 209 | +#| eval: false |
| 210 | +# Add system requirements for specific packages |
| 211 | +df <- dockerfile() |> |
| 212 | + dfi_from("rocker/r-ver:4.4.3") |> |
| 213 | + dk_add_sysreqs(c("tidyverse", "rJava")) |
| 214 | +``` |
| 215 | + |
| 216 | +### Container Exits Immediately |
| 217 | + |
| 218 | +If your container exits immediately after starting, it might be because the CMD |
| 219 | +instruction in your `Dockerfile` is not designed to keep the container running. |
| 220 | +For services, ensure the `CMD` runs a process that stays in the foreground. |
| 221 | + |
| 222 | +### Cannot Access Shiny App or Plumber API |
| 223 | + |
| 224 | +Make sure you've mapped the ports correctly with the `-p` flag and your |
| 225 | +application is configured to listen on all interfaces inside the container. |
| 226 | +For Shiny apps, this can be set with: |
| 227 | + |
| 228 | +```r |
| 229 | +options(shiny.host = '0.0.0.0') |
| 230 | +``` |
| 231 | + |
| 232 | +## Conclusion |
| 233 | + |
| 234 | +While `{dockitect}` simplifies `Dockerfile` creation, understanding how to build, |
| 235 | +run, and manage Docker containers is required for the complete workflow. This |
| 236 | +vignette covered the basics of working with Docker after generating your |
| 237 | +`Dockerfile` via `{dockitect}`. |
| 238 | + |
| 239 | +For more information, consult the [Docker documentation](https://docs.docker.com/) |
| 240 | +or the [Rocker project](https://www.rocker-project.org/) which provides pre-built |
| 241 | +Docker images for R. |
0 commit comments