class: center, middle, inverse, title-slide # Data Science for Economists ## Lecture 13: Docker ### Grant McDermott ### University of Oregon |
EC 607
--- name: toc  # Table of contents 1. [Prologue](#prologue) 2. [Docker 101](#intro) 3. [Examples](#examples) - [Base R](#r-base) - [R-dev](#r-dev) - [RStudio+](#rstudio+) 4. [Write your own Dockerfiles & images](#own) 5. [Sharing files with a container](#share) 6. [Cleaning up](#clean) 7. [Conclusions](#conclusions) --- class: inverse, center, middle name: prologue # Prologue

 --- # Install Docker - [Linux](https://docs.docker.com/engine/install) - [Mac](https://docs.docker.com/docker-for-mac/install/) - Windows (install varies by version) - [Windows 10 Pro / Education / Enterprise](https://docs.docker.com/docker-for-windows/install/) - [Windows 10 Home](https://docs.docker.com/docker-for-windows/install-windows-home/) - [Windows 7 / 8](https://docs.docker.com/toolbox/toolbox_install_windows/) --- class: inverse, center, middle name: intro # Docker 101

 --- # Motivation Have you ever... -- - tried to install a program or run someone else's code, only to be confronted by a bunch of error messages (missing packages, dependencies, etc.)? -- - shared your code and data with someone else, only for _them_ to be confronted by a bunch of error messages (missing packages, dependencies, etc.)? -- - re-run your _own_ code after updating some packages, only to find that it no longer works or the results have changed? --
 Containers are way to solve these and other common software problems. -- ### Docker By far the most widely used and best supported container technology. While there are other container platforms around, when I talk about "containers" in this lecture, I'm really talking about [**Docker**](https://www.docker.com/). --- # The "container" analogy You know those big shipping containers used to transport physical goods? .pull-left[ ![Source: https://www.pangeacontainers.nl/](pics/containerschip2.jpg) ] .pull-right[ ![](pics/container-truck.jpg) ] They provide a standard format for transporting all kinds of goods (TVs, fresh produce, whatever). Moreover, they are stackable and can easily be switched between different transport modes (ship, road, rail). -- Docker containers are the software equivalent. - physical goods <-> software - transport modes <-> operating systems --- # In even simpler terms... A docker container is just the software equivalent of a box.† .footnote[† This description (the whole slide, really) is shamelessly stolen from [Dirk Eddelbuettel](https://dirk.eddelbuettel.com/papers/cologneRUG2020.pdf).] .pull-left[ ![kunal, CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0>, via Wikimedia Commons](pics/box.jpg) ] .pull-right[ ✓ Standardized shape and form. ✓ Everyone can use. ✓ "If it runs on your machine, it will run on my machine."  --- # Why do we care? ### 1. Reproducibility If we can bundle our code and software in a Docker container, then we don't have to worry about it not working on someone else's system (and vice versa). Similarly, we don't have to worry about it not working on our own systems in the future (e.g. after package or program updates). - Examples of academic research projects using Docker for reproducibility [here](https://github.com/grantmcdermott/sceptic-priors) and [here](https://github.com/johnjosephhorton/wages_of_paycuts). ### 2. Deployment There are many deployment scenarios (packaging, testing, etc.). Of particular interest to this course are data science pipelines where you want to deploy software quickly and reliably. Need to run some time-consuming code up on the cloud? Save time and installation headaches by running it through a suitable container, which can easily be deployed to a cluster of machines too. --- # How it works 1. Start off with a stripped-down version of an operating system. Usually a Linux distro like Ubuntu. 2. Install _all_ of the programs and dependencies that are needed to run your code. 3. (Add any extra configurations you want.) 4.  Can also be compressed to save space. ] --
 **Summary:** Containers are like mini, portable operating systems that contain everything needed to run some piece of software (but nothing more!). --- # The big idea  .pull-right[*Credit: [Julia Evans](https://twitter.com/b0rk/status/1237464479811633154). (Buy the [zine](https://wizardzines.com/zines/containers/)!)*] --- # Quick terminology clarification **Dockerfile** ~ "The sheet music." The list of layers and instructions for building a Docker image. **Image** ~ "The MP3 file." This is the tarball that we talked about on the previous two slides. **Container** ~ "Song playing on my phone." A container is a running instance of an image. -- name: imagevscontainer
 Think of the Dockerfile as a piece of sheet music, which tells us everything we need to play a song (key, instruments, chords, tempo, etc.) The image is a recording of the music that perfectly reflects the sheet music (e.g. an MP3 file). A container is a playing instance of that file (maybe on my phone, maybe through my home speakers, etc.) --- class: inverse, center, middle name: examples # Examples

 --- # Rocker = R + Docker It should now be clear that Docker is targeted at (and used by) a bewildering array of software applications. In the realm of economics and data science, that includes every major open-source programming language and software stack.† For example, you could download and run a [Julia container](https://hub.docker.com/_/julia/) right now if you so wished. .footnote[† Building a Docker image on top of proprietary software is tricker and less common due to license restrictions. But it is still possible; see examples [here](https://github.com/mathworks-ref-arch/matlab-dockerfile) and [here](https://github.com/AEADataEditor/docker-stata).] -- But for this course, we are primarily concerned with Docker images that bundle R applications. The good news is that R has outstanding Docker support, primarily thanks to the **Rocker Project** ([website](https://www.rocker-project.org/) / [GitHub](https://github.com/rocker-org/rocker)). - For the rest of today's lecture we will be using images from Rocker (or derivatives). --- class: inverse, center, middle name: r-base # Example 1: Base R --- # Example 1: Base R For our first example, let's fire up a simple container that contains little more than a base R installation. ```bash $ docker run --rm -it rocker/r-base ``` This will take a little while to download the first time (GIF on next slide). But the container will be ready and waiting for immediate deployment on your system thereafter. --
 A quick note on these `docker run` flags: - `--rm` Automatically remove the container once it exits (i.e. clean up). - `-it` Launch with interactive (`i`) shell/terminal (`t`). - For a full list of flag options, see [here](https://docs.docker.com/engine/reference/run). --- # Example 1: Base R (cont.) As promised, here is a GIF of me running the command on my system. The whole thing takes about a minute and launches directly into an R session.  --- # Example 1: Base R (cont.) To see a list of running containers on your system, in a new terminal window type: ```bash $ docker ps ``` You should see something like: ```sh CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1fcdee074beb rocker/r-base "R" 35 seconds ago Up 35 seconds competent_elion ``` -- The container ID (here: `fcdee074beb`) is probably the most important bit of information. We'll be using container IDs later in the lecture. For now, just remember that you can grab them with the `$ docker ps` command. --- # Example 1: Base R (cont.) Your base R container should have launched directly into R. Feel feel to kick the tyres. Do some addition, run a regression on the `mtcars` dataset, etc. -- To exit the container, simply quit R. ```r R> q() ``` Check that it worked: ```bash $ docker ps ``` -- name: shell BTW, if you don't want to launch directly into your container's R console, you can instead start it in the bash shell. ```bash $ docker run --rm -it rocker/r-base /bin/bash ``` This time to close and exit the container, you need to exit the shell, e.g. ``` root@09dda673a187:/# exit ``` --- class: inverse, center, middle name: r-dev # Example 2: R-dev --- # Example 2: R-dev One of Docker's exemplar uses is testing software ahead of time. For example, we can safely test a new version of R in a Docker container before upgrading. -- In that vein, we can also test the development version of R via the [`rocker/drd`](https://hub.docker.com/r/rocker/drd) image. - At the time of writing this slide, the release of R version 4.1.0 was just a few days away. So, this provides a convenient way to test drive some of the [new features](https://cran.rstudio.com/) (a native pipe, lambda functions, etc.) ```bash $ docker run --rm -it rocker/drd ```  --- class: inverse, center, middle name: rstudio+ # Example 3: RStudio+ --- # Example 3: RStudio+ The Rocker Project works by layering Docker images on top of each other in a [grouped stack](https://github.com/rocker-org/rocker#use-cases). An important group here is the [**versioned**](https://github.com/rocker-org/rocker-versioned2#version-stable-rocker-images-for-r--400) stack. ![](pics/rocker-versioned.png) -- Allows us to easily spin up different versions of R (3.6.1, 4.0.2, etc), plus extra layers. --- # Example 3: RStudio+ (cont.) Let's try the [`tidyverse`](https://hub.docker.com/r/rocker/tidyverse) image from this versioned stack, which layers base R + RStudio + tidyverse. I'll specify R 4.0.0 as my base image. *Again, this next line will take a minute or three to download and extract the first time. But the container will be ready for immediate deployment on your system thereafter.* --- name: tverseinit count: false # Example 3: RStudio+ (cont.) Let's try the [`tidyverse`](https://hub.docker.com/r/rocker/tidyverse) image from this versioned stack, which layers base R + RStudio + tidyverse. I'll specify R 4.0.0 as my base image. ```bash $ docker run -d -p 8787:8787 -e PASSWORD=pswd123 rocker/tidyverse:4.0.0 ``` - `-d` Detach (i.e. run as background process). - `-p 8787:8787` Share a port with the host computer's browser. - `-e PASSWORD=pswd123` Password for logging on to RStudio Server. - `rocker/tidyverse:4.0.0` Use the [`tidyverse`](https://hub.docker.com/r/rocker/tidyverse) image built on top of R 4.0.0. -- If you run this... nothing seems to happen. Don't worry, I'll explain on the next slide. - Confirm for yourself that it's actually running with `$ docker ps`. (Windows users should definitely do this because you'll need the container ID shortly.) -- name:username **Aside.** All RStudio(+) images in the Rocker stack require a password. Pretty much anything you want except "rstudio", which is the default username. On that note, if you don't like the default "rstudio" username, you can choose your own by adding `-e USER=myusername` to the above command. --- # Example 3: RStudio+ (cont.) Unlike, the "r-base" container, this time we aren't immediately taken to our R environment. **Reason:** Our container is running RStudio Server, which needs to be opened up in a browser. -- So we need to point our browsers to the relevant IP address _plus_ the opened `:8787` port: - **Linux/Mac:** http://localhost:8787 - **Windows:** Type in `$ docker inspect <containerid> | grep IPAddress` to get your IP address (see [here](https://stackoverflow.com/a/46310428)). Note that this information was also displayed when you first launched your Docker Quickstart Terminal. For example: .small75[ ``` ## . ## ## ## == ## ## ## ## ## === /"""""""""""""""""\___/ === ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~ \______ o __/ \ \ __/ \____\_______/ docker is configured to use the default machine with IP `<IP_ADDRESS>` For help getting started, check out the docs at https://docs.docker.com ``` ] -- name: login So this Windows user would point their browser to http://<IP_ADDRESS>:8787. --- # Example 3: RStudio+ (cont.) Here's the login-in screen that I see when I navigate my browser to the relevant URL. ![](pics/rocker-rstudio-login.png) -- Sign in with your "rstudio" + "pswd123" credential combination. --- # Example 3: RStudio+ (cont.) And here I am in RStudio Server running through Docker! (Pro-tip: Hit F11 to go full-screen.) ![](pics/rocker-rstudio.png) --- count: false # Example 3: RStudio+ (cont.) I can also load the **tidyverse** straight away. (We can ignore those warning messages.) ![](pics/rocker-rstudio-tidyverse.png) --- # Example 3: RStudio+ (cont.) To stop this container, you would grab the container ID (i.e. with `$ docker ps`) and then run: ```bash $ docker stop <containerid> ``` Please don't do this yet, however! I want to continue using this running container in the next section. --
 **Aside:** Recall that we instantiated this container as a detached/background process (`-d`). ```bash $ docker run `-d` -p 8787:8787 -e PASSWORD=pswd123 rocker/tidyverse:4.0.0 ``` If you dropped the `-d` flag and re-ran the above command, your terminal would stay open as an ongoing process. (Try this for yourself later.) - Everything else would stay the same. You'd still log in at `<IPADDRESS>:8787`, etc. - However, I wanted to mention this non-background process version because it offers another way to shut down the container: Simply type `CTRL+c` in the (same, ongoing process) Terminal window. Again, try this for yourself later. --- # Example 3: RStudio+ (cont.) I'll end this example by reiterating the stacked (or _layered_) nature of the Docker workflow. To prove this, consider what happens when I instantiate the [`r-ver:4.0.0`](https://hub.docker.com/r/rocker/r-ver) image at the base of Rocker's versioned stack. -- ![](pics/r-dev-4_0_0.png) --- # Example 3: RStudio+ (cont.) I'll end this example by reiterating the stacked (or _layered_) nature of the Docker workflow. To prove this, consider what happens when I instantiate the [`r-ver:4.0.0`](https://hub.docker.com/r/rocker/r-ver) image at the base of Rocker's versioned stack. **TL;DR** I am immediately taken into a running R 4.0.0 container. - All those messages — `a4a2a29f9ba4: Already exists` etc. — are Docker confirming that it already has the necessary layers for building this (parent) container. - No need to download or build any new layers. -- This layered approach is not unique to the Rocker stack. It is integral to Docker's core design. - Cache existing layers. Only (re)build what we have to do. - Modularity reduces build times, makes containers easy to share and customize. -- All of which provides a nice segue to our next section... --- class: inverse, center, middle name: own # Write your own Dockerfiles & images

 --- # Add to an existing container The easiest way to start writing our own Docker images is by layering on top of existing containers. - Remember: Like an [ogre](https://www.youtube.com/watch?v=aJQmVZSAqlc), Docker is all about the layers. -- Let's see a simple example where we add an R library to our `tidyverse:4.0.0` image. First, make sure that the container is still running. You should see something like: ```bash $ docker ps ``` ```bash CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 802dbd3841c7 rocker/tidyverse:4.0.0 "/init" 8 minutes ago Up 8 minutes <IP_ADDRESS>:8787->8787/tcp, :::8787->8787/tcp sweet_maxwell ``` *(If you don't see something like the above, please re-start your container and then log-in to RStudio Server, using the same steps that we saw [previously](#tverseinit).)* -- Once you are in RStudio, install **data.table** like you would any normal R library. - I'm not going to show this with a GIF, but either use RStudio's library installer or run `install.packages("data.table")`. --- # Add to an existing container (cont.) Okay, data.table should now be installed on your running container. **Question:** If you stopped your container and restarted it, would data.table still be there? -- **Answer:** No! -- Remember, the whole point of Docker is to always start from the same pristine state. -- So, we have to commit these changes as part of a new (different) pristine state. The good news is that this is going to look very similar to our Git workflow. I'm going to show you how on the next slide to keep everything in one place... --- # Add to an existing container (cont.) **Step 1:** Run `docker ps` to ID the running container. We've already done this, but still... ```bash $ docker ps ``` ```bash CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 802dbd3841c7 rocker/tidyverse:4.0.0 "/init" 8 minutes ago Up 8 minutes <IP_ADDRESS>:8787->8787/tcp, :::8787->8787/tcp sweet_maxwell ``` -- **Step 2.** Grab the container ID (in my case: `802dbd3841c7`). We're going to use this to commit our changes and create a new Docker image, which I'll call `tidyverse_dt`. ```bash $ docker commit -m "tidverse + data.table" 802dbd3841c7 tidyverse_dt:4.0.0 ``` Again, this should feel _very_ familiar to our Git workflow. We even wrote ourselves a helpful commit message. Note that I added a version tag (i.e. `:4.0.0`). This is optional, but good practice. Here, I'm reminding myself that I've built on top of the R 4.0.0 versioned stack. -- **Step 3.** Profit. (There's no step 3. Just confirm for yourself that your image has been created.) ```bash $ docker images ``` --- # Adding things outside of R? For the simple example on the previous slide, we installed a single R package. But the process would work exactly the same if we did any other operations from within R(studio). - Install multiple packages - Save datasets, scripts, figures, etc. -- **Question:** What happens if we want to install/update something outside of R(Studio)? Say, Ubuntu system libraries or another program like Python? -- **Answer:** It still works exactly the same.  Either: - Launch directly into the shell to start with (remember: [here](#shell)). Or, - Use [`docker exec`](https://docs.docker.com/engine/reference/commandline/exec/) to open the shell of a running container. For example:
 $ docker exec -it 802dbd3841c7 bash
 root@802dbd3841c7:/# apt update -y && apt install htop
 root@802dbd3841c7:/# htop ## Show all available CPU cores. Press 'q' to quit.  -- (Obviously, you'd now have to commit this change to add `htop` to your image.) --- # Aside: Stop your container(s) Okay, now is a good time to stop your container if you haven't done so already. Grab your container ID and run: ```bash $ docker stop <container-id> ``` Alternatively, you can stop all running containers with the following command: ```bash $ docker stop $(docker ps -q) ``` --- # Write your own Dockerfile The interactive approach to building Docker images — i.e. committing changes to a running container — is a convenient way to get up and running quickly. However, at some point you'll probably want to start writing your own `Dockerfiles`. - Remember: `Dockerfiles` are the "sheet music" of the whole operation. These are simple text files that provide the full set of (shell) instructions for building our Docker images. -- There is a whole host of [commands and considerations](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) for writing `Dockerfiles` — all of which I am going to skip for this lecture. (We simply don't have the time.) -- BUT... I will briefly say that the Rocker Project again has our backs with a bunch of [ready-made scripts](https://github.com/rocker-org/rocker-versioned2#modifying-and-extending-images-in-the-new-architecture) for building on and extending their Docker images. -- For example, if we wanted to modify the `r-ver4.0.0` image so that it also included Python, our Dockerfile would be as simple as the following two lines: ```bash FROM rocker/r-ver:4.0.0 RUN /rocker_scripts/install_python.sh ``` .pull-right[*(Continues on next slide.)*] --- # Write your own Dockerfile (cont.) ```bash FROM rocker/r-ver:4.0.0 RUN /rocker_scripts/install_python.sh ``` -- Try this yourself by creating a file called `Dockerfile`† comprising the above lines. .footnote[†Every `Dockerfile` is called exactly that. Only one `Dockerfile` is allowed per (sub) directory.] -- Next, build your Docker image from this `Dockerfile` using the following shell command. I'm going to call my image `r_py` and give it the "4.0.0" version stamp (both choices being optional). **Important:** Make sure that your shell/terminal is in the same directory as the `Dockerfile`when you run this command. ```bash $ # docker build --tag <name>:<version> <directory> $ docker build --tag r_py:4.0.0 . ``` -- This will take a minute to pull everything in. But your `r_py` image with be ready for immediate deployment thereafter, and now includes Python and [reticulate](https://rstudio.github.io/reticulate/). ```bash $ docker run -it --rm r_py:4.0.0 ``` --- # Write your own Dockerfile (cont.) Okay, one last tip about writing your own Dockerfiles. Let's say we wanted to add an R package (e.g. data.table) to our `r_py` image at build time. How could we do this? -- Well, remember that Dockerfiles are (basically) just a set of shell instructions. So we can tell our Dockerfile to install an R package via an appropriate bash command like `Rscript`.† - We also need to pre-pend any bash command with the special Docker verb `RUN`. .footnote[† We covered `Rscript` back in the [shell lecture](https://raw.githack.com/uo-ec607/lectures/master/03-shell/03-shell.html#rscript).] -- Our Dockerfile thus becomes: ```bash FROM rocker/r-ver:4.0.0 RUN /rocker_scripts/install_python.sh RUN R -e "install.packages('data.table')" ``` -- If you build this image you'll see that it completes almost instantly... because the first two lines (i.e. layers) have already been cached. Clever! --- # Automated Dockerfiles Say that you have an existing research project or repo. Is there an easy way to write a Dockerfile / Docker image based on the contents? **Answer:** Yes! I don't have time to go into details, but automated Docker tools include: - [`containerit`](https://o2r.info/containerit/) - [`repo2docker`](https://repo2docker.readthedocs.io/en/latest/) Check them out. (I have a small `containerit` demo [here](https://github.com/grantmcdermott/containerit-demo).) --- # Docker Hub: Share your Docker images So, you've written a cool Dockerfile that you want to share with world. What next? -- You can share your Dockerfiles and images in various ways. - For my research projects, I add a Dockerfile to the companion GitHub repo. This provides a convenient way for others to reproduce the (potentially complex) computing environment that I used for conducting my analysis. (Example [here](https://github.com/grantmcdermott/sceptic-priors#docker).) The most popular way to share Docker images is by hosting them on [**Docker Hub**](https://hub.docker.com/). - I'm not going to show you how to do that here. But the good news is that it's very straightforward. See [here](https://jsta.github.io/r-docker-tutorial/04-Dockerhub.html) for a quick walkthrough. --- class: inverse, center, middle name: share # Sharing files with a container

 --- # Prep: Stop all running containers *This next section is all about sharing files and folders between your computer and a container. To avoid unexpected behaviour, it would be best to stop all running containers before proceeding.* ```bash $ docker stop $(docker ps -q) ``` --

 *You should be good to continue now...* --- # Share files by mounting volumes Each container runs in a sandboxed environment and cannot access other files and directories on your computer unless you give it explicit permission. -- To share files with a container, the `-v` (mount volume) flag is your friend. - Adopts a **LHS:RHS** convention, where LHS = `path/on/your/computer/` and RHS = `path/on/the/container`. --
 For example, say I have a folder on my computer located at `/home/grant/coolproject`. I can make this available to my "tidyverse" container by running: ```bash $ docker run `-v /home/grant/coolproject:/home/rstudio/coolproject` \ $ -d -p 8787:8787 -e PASSWORD=pswd123 rocker/tidyverse:4.0.0 ``` --
 PS — I'll get back to specifying the correct RHS path in a couple of slides. --- # coolproject The coolproject directory is now available from RStudio running on the container. ![](pics/rocker-rstudio-share.png) --- # pwd In the previous example, I provided the absolute LHS path to `/home/grant/coolproject`. The reason is that Docker doesn't understand relative paths for mounting external volumes. - E.g. I couldn't use `-v .:/home/rstudio` or `-v coolproject:home/rstudio`. -- But there _is_ a convenient shortcut for mounting the host computer's present working directory: Use \`pwd\` (including the backticks). ```bash $ docker run -v \`pwd`:/home/rstudio/coolproject \ $ -d -p 8787:8787 -e PASSWORD=pswd123 rocker/tidyverse:4.0.0 ``` -- This shortcut effectively covers the most common relative path case (i.e. linking a container to our present working directory). You can also specify sub-directories. - E.g. -v \`pwd\`/pics:/home/rstudio --- # Choosing the RHS mount point In the previous example, I specified the RHS mount point as `/home/rstudio/coolproject`. How did I know this would work? -- The short answer is that `/home/rstudio` is the default user's home directory for images in the RStudio+ stack. If you're running a container from this stack, you should almost always start your RHS with this path root.† .footnote[† Exception: If you assigned a different default user than "rstudio" ([back here](#username)).] -- We have to be be specific about mounting under the user's home directory, because RStudio Server limits how and where users can access files. (This is a security feature that we'll revisit in the next lecture on cloud computing.) -- OTOH the `/coolproject` directory name is entirely optional. Call it whatever you want... though using the same name as the linked computer directory obviously avoids confusion. - Similarly, you're free to add a couple of parent directories. I could have used `-v /home/grant/coolproject:/home/rstudio/parentdir1/parentdir2/coolproject` and it would have worked fine. --- # Choosing the RHS mount point (cont.) Choosing a specific RHS mount point is less important for non-RStudio+ containers. Still, be aware that the `/home/rstudio` path won't work for our r-base container from earlier. - Reason: There's no "rstudio" user. (Fun fact: When you run an r-base container you are actually logged in as root.) -- For non-Rstudio+ containers, I recommend a general strategy of mounting external volumes on the dedicated `/mnt` directory that is standard on Linux. For example: ``` $ docker run -it --rm -v /home/grant/coolproject:/mnt/coolproject r-base /bin/bash root@958d28472eb0:/# cd /mnt/coolproject/ root@958d28472eb0:/mnt/coolproject# R ``` --- class: inverse, center, middle name: clean # Cleaning up

 --- # Docker images As I keep emphasizing, Docker is fantastic. It allows us to very quickly share and access different software environments, with all the reproducibility and deployment benefits that this entails. -- The "downside" of this convenience is that Docker images require disk space. - For example, the `tidyverse` image that we spun up earlier takes up 2.6 GB. - Not _huge_ given then size of modern hard drives... but you can quickly eat up a good chunk of disk space once you start building Docker images regularly. -- To see a list of the images1 on your system, simply type: ```bash $ docker images ``` .footnote[1 [Remember](#imagevscontainer): Images are distinct from containers.] --- # Removing images Running the previous command on my system, here's part of what I see. ![](pics/docker-images.png) -- To remove a particular image (or set of images), we use the `docker rmi <imageid>` command. For example, I could remove both the "rocker/tidyverse" and "rocker/r-ver" images above with: ```bash $ docker rmi 6b67807352ea daceaa48a457 ``` (Feel free to try this yourself. But don't worry if you'd like to keep the equivalent images on your machine for now.) --- # Pruning Recall that Docker makes heavy used of cached layers to speed up build times. I mention this because, while the `docker rmi` command normally works great, it doesn't necessarily handle "dangling" images or build caches. - Basically, intermediate objects that are no longer being used. This should not matter much for the examples that we've seen today. But these dangling images can waste quite a bit of disk space once you've been building your own Dockerfiles for a while. -- To fix this, we use the more aggressive `$ docker <object> prune` command, where `<object>` could be an image, etc. There's also a convenient shorthand for cleaning multiple objects at once: ```bash $ docker system prune ``` I frequently use this on my own system. (More on pruning [here](https://docs.docker.com/config/pruning/).) --- class: inverse, center, middle name: conclusions # Conclusions

 --- # Conclusions Docker makes it easy to configure and share software environments. - A self-contained "box" with everything needed to run a project or application. - If it runs on your machine, it will run on my machine. - Great for reproducibility, testing, and deployment. Terminology analogy - Dockerfile = sheet music - Docker image = MP3 recording - Container = MP3 being played on my phone, etc. R users are spoilt, thanks to the Rocker Project. Easy to build our own Dockerfiles on top of this, or from scratch if we want. - Example (interactive terminal running base R 4.0.0) ```bash $ docker run -it --rm rocker/r-ver:4.0.0 ``` *(See next slide for a list of key commands.)* --- # Key commands - `docker help` list of available commands - `docker run` downloads (if needed) and runs an image. Useful flags include: - `--rm` remove after run - `-it` interactive terminal - `-v host/path:container/path` share (mount) a directory -`-p 8787:8787` share a browser port: here 8787 - `docker ps` list of currently running containers - `docker stop <container-ids>` stop one or more running containers - `docker images` list all installed images - `docker rmi <imageids>` remove one or more images - `docker system prune` catch all clean-up (stop any running containers, remove any dangling images, etc.) --- # Further reading ### Documentation - [Rocker website](https://www.rocker-project.org/) - [R Journal article (Nüst et. al., 2020)](https://journal.r-project.org/archive/2020/RJ-2020-007/index.html) - [Docker documentation](https://docs.docker.com/) ### Tutorials - [Using R via Rocker](https://dirk.eddelbuettel.com/papers/cologneRUG2020.pdf) (Excellent overview and slidedeck from Dirk Eddelbuettel, one of the originators of the Rocker Project.) - [Using Docker for Data Science](https://www.robertmylesmcdonnell.com/content/posts/docker/) (Very thorough walkthrough, with a focus on composing your own Dockerfiles from scratch.) - [ROpenSci Docker Tutorial](http://ropenscilabs.github.io/r-docker-tutorial) (Another detailed and popular tutorial, albeit outdated in parts.) - [Introduction to Docker](https://carpentries-incubator.github.io/docker-introduction/index.html) (Yet another comprehensive tutorial available from The Carpentries Incubator.) --- name: toc2 # Table of contents 1. [Prologue](#prologue) 2. [Docker 101](#intro) 3. [Examples](#examples) - [Base R](#r-base) - [R-dev](#r-dev) - [RStudio+](#rstudio+) 4. [Write your own Dockerfiles & images](#own) 5. [Sharing files with a container](#share) 6. [Cleaning up](#clean) 7. [Conclusions](#conclusions)


African Print
Ladies'Crop Tops
Men Casual Wear
Men's Official Wear
Men's Formal Wear
Ladies Sweat Pants


[gecode-users] setup on OS X
Guido Tack
tack at gecode.org
Mon Jun 14 23:13:22 CEST 2010
Hi Oliver,
thanks for the hints. Actually, I had the same problems and already fixed the section in the MPG tutorial, but we haven't quite finished it for the next release yet. Sorry you had to re-discover it on your own!
Cheers,
Guido
Oliver Mooney wrote:
> Hi all,
>
> I just wanted to document one issue I had getting set up, and how I resolved it. I'm using the binary download for OS X users. I'm on 10.6 'Snow Lepoard'. Section 2.3.2 of the Modeling and Programming with Gecode manual directs OS X users to adjust the linker options to include ' -framework gecode' but when I did so the linker complained of not being able to resolve the Gecode symbols. Instead I added the framework by right-clicking on the first entry under the 'Targets' group, picking 'Add', picking 'Existing Frameworks...' and then picking the gecode framework from the list. The project (the send more money example) then compiled successfully.
>
> I had another issue where I'd omitted the minus signs for the MONEY side of the linear equation, but that's mostly down to my poor eyesight!
>
> I'm looking forward to getting to grips with Gecode!
>
> Oliver.
> _______________________________________________
> Gecode users mailing list
> users at gecode.org
> https://www.gecode.org/mailman/listinfo/gecode-users
--
Guido Tack, http://people.cs.kuleuven.be/~guido.tack/
More information about the users
mailing list


See a Nimiq address in different kind of formats.
Get wallet balance on main, test, dev or bounty.
Generate new address and see additional information.
Generate an offline transaction with your 24 words or private key in HEX format.
See corresponding wallet information based on the 24 words.
Broadcast offline generated transaction to the Nimiq network.
Sign messages with your 24 words to proof ownership of an address.
Verify signed message with proof.


Welcome to Knappsack!
Please login:
[[#{mobile.login.alert.registration.success}]]
[[#{mobile.login.alert.registration.error}]]
Or log in with these providers:
Please login:
[[#{mobile.login.alert.registration.success}]]
[[#{mobile.login.alert.registration.error}]]
Or log in with these providers:
The use of Knappsack is currently by invitation only. If you have not received an invitation, you will not be able to create an account.


{% extends "routml_app/layout.html" %} {% block body %}
Your short URL is:
Copied!
Return to Home Page


Choose your state from the select box over on the right. This dashboard will show all states if nothing is selected.
Average Age of Fatality
Fatalities Per Month


| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.expect_crop |
( |
|
self, |
|
|
|
left_x = None , |
|
|
|
right_x = None , |
|
|
|
top_y = None , |
|
|
|
bottom_y = None |
|
) |
| |
Setup a mox expectation to images_stub._Crop.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.expect_datatore_lookup |
( |
|
self, |
|
|
|
blob_key, |
|
|
|
expected_result |
|
) |
| |
Setup a mox expectation to datastore.Get.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.expect_encode_image |
( |
|
self, |
|
|
|
data, |
|
|
|
mime_type = images_service_pb.OutputSettings.JPEG |
|
) |
| |
Setup a mox expectation to images_stub._EncodeImage.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.expect_open_image |
( |
|
self, |
|
|
|
blob_key, |
|
|
|
dimensions = None , |
|
|
|
throw_exception = None , |
|
|
|
mime_type = 'JPEG' |
|
) |
| |
Setup a mox expectation to images_stub._OpenImageData.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.expect_resize |
( |
|
self, |
|
|
|
resize |
|
) |
| |
Setup a mox expectation to images_stub._Resize.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_invalid_options |
( |
|
self | ) |
|
Tests an image request with an invalid size.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_invalid_url |
( |
|
self | ) |
|
Tests an image request with an invalid path.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_key_not_found |
( |
|
self | ) |
|
Tests an image request for a key that doesn't exist.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_not_get |
( |
|
self | ) |
|
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_open_image_throws |
( |
|
self | ) |
|
Tests OpenImage raises an exception.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_parse_options |
( |
|
self | ) |
|
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_parse_path |
( |
|
self | ) |
|
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_run_no_resize_no_crop |
( |
|
self | ) |
|
Tests an image request without resizing or cropping.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_run_resize |
( |
|
self | ) |
|
Tests an image request with resizing.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_run_resize_and_crop |
( |
|
self | ) |
|
Tests an image request with a resize and crop.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_run_resize_and_crop_png |
( |
|
self | ) |
|
Tests an image request with a resize and crop in PNG.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_run_resize_and_crop_with_padded_blobkey |
( |
|
self | ) |
|
Tests an image request with a resize and crop on a padded blobkey.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_run_resize_with_padded_blobkey |
( |
|
self | ) |
|
Tests an image request to resize with a padded blobkey.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_run_resize_without_working_images_stub |
( |
|
self | ) |
|
Tests requesting a resized image without working images stub.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_no_resize |
( |
|
self | ) |
|
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_no_resize_gif |
( |
|
self | ) |
|
Tests no resizing in GIF.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_no_resize_png |
( |
|
self | ) |
|
Tests no resizing in PNG.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_no_resize_tiff |
( |
|
self | ) |
|
Tests no resizing in TIFF.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_not_upscaled |
( |
|
self | ) |
|
Tests that an image smaller than default serving size is not upsized.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_original_size |
( |
|
self | ) |
|
Tests that s0 parameter serves image at the original size.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_resize |
( |
|
self | ) |
|
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_resize_and_crop_landscape |
( |
|
self | ) |
|
Tests resizing and cropping on a landscape image.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_resize_and_crop_portrait |
( |
|
self | ) |
|
Tests resizing and cropping on a portrait image.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_resize_and_crop_portrait_png |
( |
|
self | ) |
|
Tests resizing and cropping on a portrait PNG image.
| def google.appengine.tools.devappserver2.blob_image_test.BlobImageTest.test_transform_image_resize_png |
( |
|
self | ) |
|
The documentation for this class was generated from the following file:
- code/googleappengine-read-only/python/google/appengine/tools/devappserver2/blob_image_test.py


Precious angel under the sun,
How was I to know you'd be the one
To show me I was blinded, to show me I was gone?
How weak was the foundation I was standing upon?
Now there's spiritual warfare, flesh and blood breaking down,
You either got faith or you got unbelief and there ain't no neutral ground.
The enemy is subtle: how be it we're deceived
When the truth's in our hearts and we still don't believe?

My so-called friends have fallen under a spell,
They look me squarely in the eye and they say, "Well, all is well."
Can they imagine the darkness that will fall from on high
When men will beg God to kill them and they won't be able to die?
Sister, let me tell you about a vision that I saw:
You were drawing water for your husband, you were suffering under the law,
You were telling him about Buddha, you were telling him 'bout Muhammad in one breath,
You never mentioned one time the man who came and died a criminal's death.

Precious angel, you believe me when I say,
"What God has given to us no man can take away"?
We are covered in blood, girl, you know, both our forefathers were slaves,
Let us hope they've found mercy in their bone-filled graves.


I design, code and modify websites & mobile apps, from layout to function and according to a client's specifications. I also have experience in many different areas to provide a well rounded experience, while using different coding languages such as JavaScript, React, Angular and Python.
This is my first website after learning html and css in a few days. A resume with some of my work experience from the last few years.
My first website with mutliple pages and a few fun facts about the TV show.
Fully functional calucaltor coded in HTML and CSS with a little bit of JavaScript.
I am a big fan of Lil Wayne and did my second functional website sharing facts about him.
This alarm clock is not only aesthetically pleasing but also features a wake up song once you plug in the time you would like.
Tsunami Mixed Martial Arts
I kickbox in my spare time and revamped a website for the gym I am currently going to. These projects spanned over 5 weeks and you can see the progress.


ALL ABOUT ME!!
Hey there! So I grew up in the suburbs of Milwaukee, Wisconsin. Lived most of my live in that area, when to college at University of Wisconsin-Milwaukee where I got my bachlours in criminal justice. Soon after graduating, I moved down to Chicago, Illinois to move in with my girlfriend (now fiancee) while she finished her masters at the University of Chicago.
When I first moved down to Chicago, I got one of the first jobs I could to pay the bills, working as a dealer at Horseshoe Hammond Casino in Hammond, Indiana. I worked there for five years working in the Table Games department working my way up to a Dual-Rate Supervisor. After five years of working grave shift, losing sleep, working weekends and holidays, I decided to leave it all behind to focus on a passion of mine. Enter: Dev Bootcamp!
Now, I never think of myself as a quirky person, or even a very interesting person. I have similar interests as any normal twenty-something year old guy. However, I do have an extreme love for Walt Disney World. Really, who doesnt love Walt Disney World? I did an intership in Walt Disney World in 2008, and have wanted to go back to visit every year since.


The Gradient object.
Creates a gradient object
Checks whether the gradient is equal to the supplied gradient.
The gradient stops on the gradient ramp.
Copyright © 2011 Jürg Lehni & Jonathan Puckey. All Rights Reserved.


Cultural news aggregation site with a custom RSS module that enables periodic updates from RSS, twitter, flickr and YouTube feeds.
This product was concieved by 24 Hour Museum journalist Jon Pratty, and used guardian.com as inspiration for the content design patterns. Built on Drupal, all you do is pick interesting feeds, and the site updates itself!
Girogio Armani and DKNY Commissions Management System and Flash Sales Commisions management built on top of existing sales audit and employee database systems, it allows sales staff to see how much commission they have earned from any point of sale terminal.
Mousharaka graphic design conference was the first of its kind in Doha. Hired by Virginia Commonwealth University to execute the website for the conference
We designed dual language interface (Arabic/English), and interfaced with online conference paper manager.
In addition to implementation, I arranged secure hosting for the site.
Menu structures for both English and Arabic content were fine tuned here, to ensure they made sense and provided good wayfinding for both audiences.


{% extends "pathways/base.html" %} {% block content %} An email has been sent with instructions to reset your password {% endblock content %}


Jim has a Bachelor’s of Science in Computer Science from University of Illinois at Chicago. Jim has valuable experience in C/C++, Java and C#. He also has mobile development experience using Xamarin Forms and Android Studio. He has also worked on web related projects using Angular 5,JavaScript, HTML, and CSS.
Jim has worked with various clients during his time at Avanade and he ensures that the solutions provided to the clients meet the requirements. Jim has developed mobile applications using Xamarin Forms that provided clients with a cross-platform solution which helped simplified their daily job routine. Jim also did web development using technologies such as Angular and Sitecore.
Jim created installers for the Superload application using WIX, reducing installation time by approximately 25% and he set up VM servers for quality testing, resulting in a 75% success rate on tested machine. Jim also documented process to use WIX, enabling fellow teammates to use the application.
Jim served as a teaching assistant for Introduction to Computing and Programming, for approximately 8 hours a week. Jim assisted the professor by grading nearly 50 exams and weekly homework assignments. Jim also tutored students in C++ and critiqued them on their projects
Overall GPA: 3.69/4.0
Major GPA: 3.93/4.0
Run & Gun is an arcade shooter that was made using Unreal Engine 4 (C++). The objective of the game is for the player to score as many points as possible well being trap in a pit with infinite enemy spawning. The player is given three lives, and the game will reach a game over if all lives are spent.


Reports integer multiplications or left shifts which are implicitly cast to long.
For example:
void x(int i) {
long val = 65536 * i;
}
Such multiplication is often a mistake, as overflow truncation may occur unexpectedly.
Converting the int literal to a long literal (65536L) fixes the problem.


Welcome to Pig Dice!
Play against our A.I.
Player 1 turn score:
0
Player 1 total score:
0
Player 2 turn score:
0
Player 2 total score:
0
Roll
Hold


--- layout: post title: ! 'Becoming a Headspringer: Know thy ReSharper' categories: - Developer Deep Dive - What the tech? status: publish type: post published: true meta: _edit_last: '23' s2mail: 'yes' _aioseop_keywords: resharper, shortcuts, visual studio _aioseop_description: Becoming a Headspringer post about sharpening your ReSharper skills by learning new shortcuts to help you be a more productive developer within Visual Studio. _aioseop_title: ! 'Becoming a Headspringer: Know thy ReSharper' dsq_thread_id: '835127702' ---
Since I'm new to Headspring and we are hiring, I thought I would help give an edge to anyone applying and subscribing to our blog. There are many “features” (pun attempted) that make up a Headspringer and I’m hoping my fellow Headspring bloggers will help me verbalize them through the “Becoming a Headspringer” blog series. I will be starting this series with some quick tips on ReSharper. If you do not already have ReSharper or know what it is, immediately after reading this post is as good a time as any to try it out.
I was assigned my first development project a few weeks ago and was quickly told my hand reached for the mouse too often by Mr. Justin Pope. If you know me at all, you know that I enjoy shortcuts and dislike the mouse quite a bit. In fact, at my previous job, I removed all of my team members’ mice so they would be forced to learn to navigate with the keyboard for a day. So when I was told I use the mouse too much, I knew I was going to love it at Headspring and thoroughly enjoy becoming a Headspringer. Shortly after a friendly insult, Mr. Justin Pope gave me a quick crash course in many of the common ReSharper shortcuts and I will share some of those shortcuts with you.
ctrl+n (to navigate to specific type) or ctrl+shift+n (to navigate to a specific file or folder)
ctrl+w (continue pressing w until everything you want highlighted is highlighted)
alt+del (tells you whether or not it’s safe to delete a method, property, class, etc)
ctrl+alt+f7 (shows all usages of a particular method, property, class, etc)
ctrl+p (must be just inside parentheses)
1. alt+insert (not just to insert constructor)
2. Select “Constructor” (if you already have fields defined, it will prompt if you want to initialize them)
1. Highlight what needs to become a variable
2. ctrl+alt+v
1. Navigate near the variable name
2. alt+enter
3. Select “Move to outer scope”
1. ctrl+n (to navigate to a similar class) or ctrl+shift+n (to navigate to a similar file)
2. alt+shift+l (to navigate to the file in the Solution Explorer)
3. ctrl+c (to copy)
4. ctrl+v (to paste)
5. F2 (to rename)
6. Enter (to open)
7. Start modifying the file
The shortcuts above are a small percentage of the shortcuts I found useful, but a good start to becoming a more productive developer. You may also notice that not all of these are specifically ReSharper shortcuts, some of them are Visual Studio or Windows shortcuts. Anyhow, you can find a more extensive list of ReSharper shortcuts on the Jetbrains site.
As I mentioned above, Headspring is hiring. So if you are interested in being challenged, working with smart people, and being led by a great group of people, apply!