diff --git a/docker/DOCKER_README.md b/docker/DOCKER_README.md
new file mode 100644
index 000000000..e2b1f97d0
--- /dev/null
+++ b/docker/DOCKER_README.md
@@ -0,0 +1,21 @@
+# Infection Monkey
+
+How to run Monkey Island from the docker file:
+
+Note: Ports 5000 and 5001 must be available for the island to work.
+
+## Setup
+
+Run the following commands:
+
+```sh
+sudo docker load -i dk.monkeyisland.MONKEY_VER_PLACEHOLDER.tar
+sudo docker pull mongo:4.2
+sudo mkdir -p /var/monkey-mongo/data/db
+sudo docker run --name monkey-mongo --network=host -v /var/monkey-mongo/data/db:/data/db -d mongo:4.2
+sudo docker run --name monkey-island --network=host -d guardicore/monkey-island:MONKEY_VER_PLACEHOLDER
+```
+
+## Start Infecting
+
+Open `https://<Server IP>:5000` using Google Chrome and follow the instructions. You can also visit [the Infection Monkey website](https://infectionmonkey.com) and read the in-depth Getting Started guides.
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 000000000..2637d3725
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,27 @@
+# Install python dependencies using the bitnami/python:3.7 image, which includes
+# development dependencies.
+FROM bitnami/python:3.7 as builder
+COPY ./monkey /monkey
+WORKDIR /monkey
+RUN virtualenv .
+RUN . bin/activate && \
+    cd monkey_island && \
+    pip install pipenv && \
+    pipenv sync
+
+
+# Build the final application using the bitnami/python:3.7-prod image, which
+# does not include development dependencies.
+FROM bitnami/python:3.7-prod
+RUN apt-get update && apt-get install -y iputils-ping && apt-get clean
+COPY --from=builder /monkey /monkey
+WORKDIR /monkey
+EXPOSE 5000
+EXPOSE 5001
+RUN groupadd -r monkey-island && useradd --no-log-init -r -g monkey-island monkey-island
+RUN chmod 444 /monkey/monkey_island/cc/server.key
+RUN chmod 444 /monkey/monkey_island/cc/server.csr
+RUN chmod 444 /monkey/monkey_island/cc/server.crt
+RUN mkdir /monkey_island_data && chmod 700 /monkey_island_data && chown -R monkey-island:monkey-island /monkey_island_data
+USER monkey-island
+ENTRYPOINT ["/monkey/entrypoint.sh"]
diff --git a/docker/build_docker.sh b/docker/build_docker.sh
new file mode 100755
index 000000000..6aad00bed
--- /dev/null
+++ b/docker/build_docker.sh
@@ -0,0 +1,310 @@
+WORKSPACE=${WORKSPACE:-$HOME}
+
+BUILD_DIR="$PWD/monkey"
+
+GIT=$WORKSPACE/git
+
+DEFAULT_REPO_MONKEY_HOME=$GIT/monkey
+
+ISLAND_PATH="$BUILD_DIR/monkey_island"
+ISLAND_BINARIES_PATH="$ISLAND_PATH/cc/binaries"
+
+MONKEY_ORIGIN_URL="https://github.com/guardicore/monkey.git"
+CONFIG_URL="https://raw.githubusercontent.com/guardicore/monkey/develop/deployment_scripts/config"
+NODE_SRC=https://deb.nodesource.com/setup_12.x
+ISLAND_DIR_COPY_TIMEOUT=60 #Seconds
+
+OUTPUT_NAME_TGZ="$PWD/infection_monkey_docker_$(date +%Y%m%d_%H%M%S).tgz"
+
+exit_if_missing_argument() {
+  if [ -z "$2" ] || [ "${2:0:1}" == "-" ]; then
+    echo "Error: Argument for $1 is missing" >&2
+    exit 1
+  fi
+}
+
+echo_help() {
+  echo "usage: build_appimage.sh [--help] [--agent-binary-dir <PATH>] [--branch <BRANCH>]"
+  echo "                         [--monkey-repo <PATH>] [--version <MONKEY_VERSION>]"
+  echo ""
+  echo "Creates an AppImage package for Infection Monkey."
+  echo ""
+  echo "--agent-binary-dir             A directory containing the agent binaries that"
+  echo "                               you'd like to include with the AppImage. If this"
+  echo "                               parameter is unspecified, the latest release"
+  echo "                               binaries will be downloaded from GitHub."
+  echo ""
+  echo "--as-root                      Throw caution to the wind and allow this script"
+  echo "                               to be run as root."
+  echo ""
+  echo "--branch                       The git branch you'd like the AppImage to be"
+  echo "                               built from. (Default: develop)"
+  echo ""
+  echo "--monkey-repo                  A directory containing the Infection Monkey git"
+  echo "                               repository. If the directory is empty or does"
+  echo "                               not exist, a new repo will be cloned from GitHub."
+  echo "                               If the directory is already a valid GitHub repo,"
+  echo "                               it will be used as-is and the --branch parameter"
+  echo "                               will have no effect."
+  echo "                               (Default: $DEFAULT_REPO_MONKEY_HOME)"
+  echo ""
+  echo "--version                      A version number for the AppImage package."
+  echo "                               (Default: dev)"
+
+  exit 0
+}
+
+is_root() {
+  return "$(id -u)"
+}
+
+has_sudo() {
+  # 0 true, 1 false
+  sudo -nv > /dev/null 2>&1
+  return $?
+}
+
+log_message() {
+  echo -e "\n\n"
+  echo -e "DOCKER IMAGE BUILDER: $1"
+}
+
+handle_error() {
+  echo "Fix the errors above and rerun the script"
+  exit 1
+}
+
+install_nodejs() {
+  log_message "Installing nodejs"
+
+  curl -sL $NODE_SRC | sudo -E bash -
+  sudo apt-get install -y nodejs
+}
+
+install_build_prereqs() {
+  sudo apt-get update
+  sudo apt-get upgrade -y
+
+  # monkey island prereqs
+  sudo apt-get install -y curl libcurl4 openssl git build-essential moreutils
+  install_nodejs
+}
+
+install_docker() {
+    sudo apt-get install -y docker.io
+}
+
+clone_monkey_repo() {
+  local repo_dir=$1
+  local branch=$2
+
+  if [[ ! -d "$repo_dir" ]]; then
+    mkdir -p "$repo_dir"
+  fi
+
+  log_message "Cloning files from git"
+  git clone -c core.autocrlf=false --single-branch --recurse-submodules -b "$branch" "$MONKEY_ORIGIN_URL" "$repo_dir" 2>&1 || handle_error
+}
+
+is_valid_git_repo() {
+  pushd "$1" 2>/dev/null || return 1
+  git status >/dev/null 2>&1
+  success="$?"
+  popd || exit 1
+
+  return $success
+}
+
+setup_build_dir() {
+  local agent_binary_dir=$1
+  local monkey_repo=$2
+
+  mkdir "$BUILD_DIR"
+
+  copy_entrypoint_to_build_dir
+
+  copy_monkey_island_to_build_dir "$monkey_repo/monkey"
+  add_agent_binaries_to_build_dir "$agent_binary_dir"
+
+  generate_ssl_cert
+
+  build_frontend
+}
+
+copy_entrypoint_to_build_dir() {
+    cp ./entrypoint.sh "$BUILD_DIR"
+    chmod 755 "$BUILD_DIR/entrypoint.sh"
+}
+copy_monkey_island_to_build_dir() {
+  local src=$1
+  cp "$src"/__init__.py "$BUILD_DIR"
+  cp "$src"/monkey_island.py "$BUILD_DIR"
+  cp -r "$src"/common "$BUILD_DIR/"
+  if ! timeout "${ISLAND_DIR_COPY_TIMEOUT}" cp -r "$src"/monkey_island "$BUILD_DIR/"; then
+    log_message "Copying island files takes too long. Maybe you're copying a dev folder instead of a fresh repository?"
+    exit 1
+  fi
+  cp ./server_config.json "$BUILD_DIR"/monkey_island/cc/
+}
+
+add_agent_binaries_to_build_dir() {
+  local agent_binary_dir=$1
+
+  if [ -z "$agent_binary_dir" ]; then
+    download_monkey_agent_binaries
+  else
+    copy_agent_binaries_to_appdir "$agent_binary_dir"
+  fi
+
+  make_linux_binaries_executable
+}
+
+download_monkey_agent_binaries() {
+  log_message "Downloading monkey agent binaries to ${ISLAND_BINARIES_PATH}"
+
+  load_monkey_binary_config
+
+  mkdir -p "${ISLAND_BINARIES_PATH}" || handle_error
+  curl -L -o "${ISLAND_BINARIES_PATH}/${LINUX_32_BINARY_NAME}" "${LINUX_32_BINARY_URL}"
+  curl -L -o "${ISLAND_BINARIES_PATH}/${LINUX_64_BINARY_NAME}" "${LINUX_64_BINARY_URL}"
+  curl -L -o "${ISLAND_BINARIES_PATH}/${WINDOWS_32_BINARY_NAME}" "${WINDOWS_32_BINARY_URL}"
+  curl -L -o "${ISLAND_BINARIES_PATH}/${WINDOWS_64_BINARY_NAME}" "${WINDOWS_64_BINARY_URL}"
+}
+
+load_monkey_binary_config() {
+  tmpfile=$(mktemp)
+
+  log_message "Downloading prebuilt binary configuration"
+  curl -L -s -o "$tmpfile" "$CONFIG_URL"
+
+  log_message "Loading configuration"
+  source "$tmpfile"
+}
+
+copy_agent_binaries_to_appdir() {
+  cp "$1"/* "$ISLAND_BINARIES_PATH/"
+}
+
+make_linux_binaries_executable() {
+  chmod a+x "$ISLAND_BINARIES_PATH"/monkey-linux-*
+}
+
+generate_ssl_cert() {
+  log_message "Generating certificate"
+
+  chmod u+x "${ISLAND_PATH}"/linux/create_certificate.sh
+  "${ISLAND_PATH}"/linux/create_certificate.sh "${ISLAND_PATH}"/cc
+}
+
+build_frontend() {
+  pushd "$ISLAND_PATH/cc/ui" || handle_error
+
+  log_message "Generating front end"
+  npm ci
+  npm run dist
+
+  popd || handle_error
+
+  remove_node_modules
+}
+
+remove_node_modules() {
+  # Node has served its purpose. We don't need to deliver the node modules with
+  # the AppImage.
+  rm -rf "$ISLAND_PATH"/cc/ui/node_modules
+}
+
+build_docker_image() {
+  local version=$1
+
+  docker_image_name=guardicore/monkey-island:$version
+  tar_name=./dk.monkeyisland.$version.tar
+
+  build_docker_image_tar "$docker_image_name" "$tar_name"
+  build_docker_image_tgz "$tar_name" "$version"
+}
+
+build_docker_image_tar() {
+  sudo docker build . -t "$1"
+  sudo docker save "$1" > "$2"
+}
+
+build_docker_image_tgz() {
+  mkdir tgz
+  cp "$1" ./tgz
+  cp ./DOCKER_README.md ./tgz/README.md
+  tar -C ./tgz -cvf "$OUTPUT_NAME_TGZ" --gzip .
+}
+
+agent_binary_dir=""
+as_root=false
+branch="develop"
+monkey_repo="$DEFAULT_REPO_MONKEY_HOME"
+monkey_version="dev"
+
+
+while (( "$#" )); do
+  case "$1" in
+    --agent-binary-dir)
+      exit_if_missing_argument "$1" "$2"
+
+      agent_binary_dir=$2
+      shift 2
+      ;;
+    --as-root)
+      as_root=true
+      shift
+      ;;
+    --branch)
+      exit_if_missing_argument "$1" "$2"
+
+      branch=$2
+      shift 2
+      ;;
+    -h|--help)
+      echo_help
+      ;;
+    --monkey-repo)
+      exit_if_missing_argument "$1" "$2"
+
+      monkey_repo=$2
+      shift 2
+      ;;
+    --version)
+      exit_if_missing_argument "$1" "$2"
+
+      monkey_version=$2
+      shift 2
+      ;;
+    *)
+      echo "Error: Unsupported parameter $1" >&2
+      exit 1
+      ;;
+  esac
+done
+
+log_message "Building Monkey Island Docker image."
+
+if ! $as_root && is_root; then
+  log_message "Please don't run this script as root"
+  exit 1
+fi
+
+if ! has_sudo; then
+  log_message "You need root permissions for some of this script operations. \
+Run \`sudo -v\`, enter your password, and then re-run this script."
+  exit 1
+fi
+
+install_build_prereqs
+install_docker
+
+if ! is_valid_git_repo "$monkey_repo"; then
+  clone_monkey_repo "$monkey_repo" "$branch"
+fi
+
+setup_build_dir "$agent_binary_dir" "$monkey_repo"
+build_docker_image "$monkey_version"
+
+log_message "Docker build script finished."
+exit 0
diff --git a/docker/clean.sh b/docker/clean.sh
new file mode 100755
index 000000000..f5cfacc28
--- /dev/null
+++ b/docker/clean.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# This is a utility script to clean up after a failed or successful Docker
+# image build in order to speed up development and debugging
+
+BUILD_DIR=$HOME/docker
+
+rm -rf $HOME/git/monkey
+rm -rf $BUILD_DIR/monkey
+rm -rf $BUILD_DIR/tgz
+rm $BUILD_DIR/dk.monkeyisland.*.tar
+rm $BUILD_DIR/infection_monkey_docker*.tgz
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
new file mode 100755
index 000000000..069d3619c
--- /dev/null
+++ b/docker/entrypoint.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+echo "$@"
+
+source /monkey/bin/activate
+python /monkey/monkey_island.py "$@"
diff --git a/docker/server_config.json b/docker/server_config.json
new file mode 100644
index 000000000..77e5d9855
--- /dev/null
+++ b/docker/server_config.json
@@ -0,0 +1,11 @@
+{
+  "data_dir": "/monkey_island_data",
+  "log_level": "DEBUG",
+  "environment": {
+    "server_config": "password",
+    "deployment": "docker"
+  },
+  "mongodb": {
+    "start_mongodb": false
+  }
+}