Successfully run webserver from Docker image
This commit is contained in:
parent
938e41b1c6
commit
2e6aafbcb3
19
Makefile
19
Makefile
|
@ -28,6 +28,8 @@ image:
|
|||
@: $${I}
|
||||
ifeq ($(I),composite)
|
||||
node tools/build-composite-image.js
|
||||
else ifeq ($(I),app)
|
||||
docker build . -f docker/$(I)/Dockerfile -t riju:$(I)
|
||||
else
|
||||
docker build . -f docker/$(I)/Dockerfile -t riju:$(I) --pull
|
||||
endif
|
||||
|
@ -51,13 +53,24 @@ pkg:
|
|||
|
||||
VOLUME_MOUNT ?= $(PWD)
|
||||
|
||||
P1 ?= 6119
|
||||
P2 ?= 6120
|
||||
|
||||
ifneq (,$(E))
|
||||
SHELL_PORTS := -p 127.0.0.1:$(P1):6119 -p 127.0.0.1:$(P2):6120
|
||||
else
|
||||
SHELL_PORTS :=
|
||||
endif
|
||||
|
||||
.PHONY: shell
|
||||
shell:
|
||||
@: $${I}
|
||||
ifeq ($(I),admin)
|
||||
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src -v /var/run/docker.sock:/var/run/docker.sock -v $(HOME)/.aws:/var/riju/.aws:ro -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e VOLUME_MOUNT=$(VOLUME_MOUNT) --network host riju:$(I)
|
||||
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src -v /var/run/docker.sock:/var/run/docker.sock -v $(HOME)/.aws:/var/riju/.aws -v $(HOME)/.docker:/var/riju/.docker -v $(HOME)/.terraform.d:/var/riju/.terraform.d -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e VOLUME_MOUNT=$(VOLUME_MOUNT) $(SHELL_PORTS) --network host riju:$(I)
|
||||
else ifeq ($(I),compile)
|
||||
docker run -it --rm --hostname $(I) $(SHELL_PORTS) riju:$(I)
|
||||
else
|
||||
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src -p 127.0.0.1:6119:6119 -p 127.0.0.1:6120:6120 riju:$(I)
|
||||
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src $(SHELL_PORTS) riju:$(I)
|
||||
endif
|
||||
|
||||
.PHONY: install
|
||||
|
@ -99,8 +112,6 @@ build: frontend system
|
|||
dev:
|
||||
make -j3 frontend-dev system-dev server-dev
|
||||
|
||||
### Run application code
|
||||
|
||||
### Fetch artifacts from registries
|
||||
|
||||
.PHONY: pull
|
||||
|
|
|
@ -47,7 +47,7 @@ app.get("/:lang", (req, res) => {
|
|||
analyticsEnabled,
|
||||
});
|
||||
} else {
|
||||
res.send(`No such language: ${lang}`);
|
||||
res.send(404, `No such language: ${lang}\n`);
|
||||
}
|
||||
});
|
||||
app.use("/css", express.static("frontend/styles"));
|
||||
|
|
|
@ -11,6 +11,7 @@ apt-get update
|
|||
|
||||
apt-get install -y curl gnupg lsb-release
|
||||
|
||||
curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
|
||||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
|
||||
curl -fsSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
|
||||
|
@ -21,13 +22,33 @@ ubuntu_name="$(lsb_release -cs)"
|
|||
node_repo="$(curl -sS https://deb.nodesource.com/setup_current.x | grep NODEREPO= | grep -Eo 'node_[0-9]+\.x' | head -n1)"
|
||||
|
||||
tee -a /etc/apt/sources.list.d/custom.list >/dev/null <<EOF
|
||||
deb [arch=amd64] https://apt.releases.hashicorp.com ${ubuntu_name} main
|
||||
deb [arch=amd64] https://deb.nodesource.com/${node_repo} ${ubuntu_name} main
|
||||
deb [arch=amd64] https://dl.yarnpkg.com/debian/ stable main
|
||||
deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable
|
||||
deb [arch=amd64] https://download.docker.com/linux/ubuntu ${ubuntu_name} stable
|
||||
EOF
|
||||
|
||||
packages="
|
||||
|
||||
docker-ce-cli
|
||||
jq
|
||||
less
|
||||
make
|
||||
man
|
||||
nodejs
|
||||
packer
|
||||
sudo
|
||||
tmux
|
||||
terraform
|
||||
unzip
|
||||
vim
|
||||
wget
|
||||
yarn
|
||||
|
||||
"
|
||||
|
||||
apt-get update
|
||||
apt-get install -y docker-ce-cli less make man nodejs sudo tmux unzip wget yarn
|
||||
apt-get install -y $(sed 's/#.*//' <<< "${packages}")
|
||||
|
||||
wget https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -O awscli.zip
|
||||
unzip awscli.zip
|
||||
|
|
|
@ -7,6 +7,8 @@ useradd -u "$(stat -c %u "$PWD")" -g "$(stat -c %g "$PWD")" -o -p '!' -m -N -l -
|
|||
|
||||
runuser -u riju -- touch /home/riju/.sudo_as_admin_successful
|
||||
runuser -u riju -- ln -sT /var/riju/.aws /home/riju/.aws
|
||||
runuser -u riju -- ln -sT /var/riju/.docker /home/riju/.docker
|
||||
runuser -u riju -- ln -sT /var/riju/.terraform.d /home/riju/.terraform.d
|
||||
runuser -u riju -- yarn install
|
||||
|
||||
exec runuser -u riju "$@"
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
FROM riju:compile AS compile
|
||||
FROM riju:composite
|
||||
|
||||
ENTRYPOINT ["/usr/local/sbin/my_init"]
|
||||
RUN useradd -p '!' -m -l -s /usr/bin/bash riju
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
COPY --chown=riju:riju --from=compile . ./
|
||||
COPY --chown=riju:riju --from=compile /src ./
|
||||
RUN chown root:riju system/out/*-privileged && chmod a=,g=rx,u=rwxs system/out/*-privileged
|
||||
|
||||
USER riju
|
||||
CMD ["make", "server"]
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
FROM ubuntu:rolling AS build
|
||||
FROM ubuntu:rolling
|
||||
|
||||
COPY docker/runtime/install.bash /tmp/
|
||||
COPY docker/compile/install.bash /tmp/
|
||||
RUN /tmp/install.bash
|
||||
|
||||
WORKDIR /src
|
||||
COPY Makefile ./
|
||||
|
||||
COPY system ./system/
|
||||
RUN make system
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install
|
||||
|
@ -12,9 +16,6 @@ COPY webpack.config.cjs ./
|
|||
COPY frontend/src ./frontend/src/
|
||||
RUN make frontend
|
||||
|
||||
COPY system ./system/
|
||||
RUN make system
|
||||
|
||||
COPY frontend/pages ./frontend/pages/
|
||||
COPY frontend/styles ./frontend/styles/
|
||||
COPY backend ./backend/
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euxo pipefail
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
apt-get update
|
||||
apt-get dist-upgrade -y
|
||||
|
||||
apt-get install -y curl gnupg lsb-release
|
||||
|
||||
curl -sSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
|
||||
curl -sSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
|
||||
ubuntu_ver="$(lsb_release -rs)"
|
||||
ubuntu_name="$(lsb_release -cs)"
|
||||
|
||||
node_repo="$(curl -sS https://deb.nodesource.com/setup_current.x | grep NODEREPO= | grep -Eo 'node_[0-9]+\.x' | head -n1)"
|
||||
|
||||
tee -a /etc/apt/sources.list.d/custom.list >/dev/null <<EOF
|
||||
deb https://deb.nodesource.com/${node_repo} ${ubuntu_name} main
|
||||
deb https://dl.yarnpkg.com/debian/ stable main
|
||||
EOF
|
||||
|
||||
apt-get update
|
||||
apt-get install -y clang g++ make nodejs sudo yarn
|
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
apt-get update
|
||||
apt-get dist-upgrade
|
||||
|
||||
apt-get install -y curl gnupg lsb-release
|
||||
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
|
||||
|
||||
ubuntu_name="$(lsb_release -cs)"
|
||||
|
||||
tee -a /etc/apt/sources.list.d/custom.list >/dev/null <<EOF
|
||||
deb [arch=amd64] https://download.docker.com/linux/ubuntu ${ubuntu_name} stable
|
||||
EOF
|
||||
|
||||
apt-get update
|
||||
apt-get install docker-ce docker-ce-cli containerd.io
|
||||
|
||||
sed -i "s#DOCKER_REPO_REPLACED_BY_PACKER#${DOCKER_REPO}#" /usr/local/bin/riju-deploy
|
||||
|
||||
for user in admin deploy; do
|
||||
if ! grep -vq "PRIVATE KEY" "/tmp/id_${user}.pub"; then
|
||||
echo "${user} public key was set to a private key, aborting" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IFS=" " read contents < "/tmp/id_${user}.pub"
|
||||
echo "${contents}" > "/tmp/id_${user}.pub"
|
||||
done
|
||||
|
||||
sed -Ei 's/^#?PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
|
||||
sed -Ei 's/^#?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
|
||||
sed -Ei 's/^#?PermitEmptyPasswords .*/PermitEmptyPasswords no/' /etc/ssh/sshd_config
|
||||
|
||||
passwd -l root
|
||||
useradd admin -g admin -G sudo -s /usr/bin/bash -p "$(echo "${ADMIN_PASSWORD}" | mkpasswd -s)" -m
|
||||
useradd deploy -s /usr/bin/bash -p "!"
|
||||
|
||||
for user in admin deploy; do
|
||||
mkdir -p "/home/${user}/.ssh"
|
||||
mv "/tmp/id_${user}.pub" "/home/${user}/.ssh/authorized_keys"
|
||||
chown -R "${user}:${user}" "/home/${user}/.ssh"
|
||||
chmod -R go-rwx "/home/${user}/.ssh"
|
||||
done
|
||||
|
||||
sed -i 's/^/command="sudo riju-deploy",restrict/' /home/deploy/.ssh/authorized_keys
|
||||
|
||||
cat <<"EOF" > /etc/sudoers.d/riju
|
||||
deploy ALL=(root) NOPASSWD: /usr/local/bin/riju-deploy
|
||||
EOF
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
domain="$(ls /etc/letsencrypt/live | grep -v README | head -n1)"
|
||||
|
||||
if [[ -n "${domain}" ]]; then
|
||||
echo "Detected cert for domain: ${domain}, enabling TLS" >&2
|
||||
export TLS=1
|
||||
TLS_PRIVATE_KEY="$(base64 "/etc/letsencrypt/live/${domain}/privkey.pem")"
|
||||
TLS_CERTIFICATE="$(base64 "/etc/letsencrypt/live/${domain}/fullchain.pem")"
|
||||
export TLS_PRIVATE_KEY TLS_CERTIFICATE
|
||||
if [[ "${domain}" == riju.codes ]]; then
|
||||
echo "Domain is riju.codes, enabling analytics" >&2
|
||||
export ANALYTICS=1
|
||||
else
|
||||
echo "Domain is not riju.codes, disabling analytics" >&2
|
||||
fi
|
||||
else
|
||||
echo "No certs installed in /etc/letsencrypt/live, disabling TLS" >&2
|
||||
fi
|
||||
|
||||
if [[ -n "${DETACH:-}" ]]; then
|
||||
extra_args="-d"
|
||||
elif [[ -t 1 ]]; then
|
||||
extra_args="-it"
|
||||
else
|
||||
extra_args=
|
||||
fi
|
||||
|
||||
port_args="${PORT_MAPPING:--p 0.0.0.0:80:6119 -p 0.0.0.0:443:6120}"
|
||||
|
||||
docker run --rm ${port_args} ${extra_args} \
|
||||
-e TLS -e TLS_PRIVATE_KEY -e TLS_CERTIFICATE -e ANALYTICS \
|
||||
-h riju --name "${CONTAINER_NAME:-riju-prod}" \
|
||||
"${IMAGE_NAME}:-riju:app"
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DOCKER_REPO="${DOCKER_REPO:-DOCKER_REPO_REPLACED_BY_PACKER}"
|
||||
|
||||
if (( $# != 1 )); then
|
||||
echo "usage: ssh deploy@riju COMMIT-SHA" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
commit="$1"
|
||||
|
||||
if [[ "$(echo -n "${commit}" | wc -c)" != 40 ]]; then
|
||||
echo "riju-deploy: invalid commit SHA: ${commit}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
image="${DOCKER_REPO}:app-${commit}"
|
||||
|
||||
echo "Pull image to be deployed..."
|
||||
docker pull "${image}"
|
||||
|
||||
echo "Start new image in test container..." >&2
|
||||
CONTAINER_NAME=riju-test IMAGE_NAME="${image}" DETACH=1 \
|
||||
PORT_MAPPING="-p 127.0.0.1:6119:6119" riju
|
||||
|
||||
echo "Wait for web server to come up..." >&2
|
||||
sleep 10
|
||||
|
||||
echo "Test web server health..." >&2
|
||||
curl -fsSL http://localhost:6119 | head -n15
|
||||
|
||||
echo "Tear down test container..." >&2
|
||||
docker stop riju-test
|
||||
|
||||
echo "Retag production image..." >&2
|
||||
docker tag "${image}" riju:app
|
||||
|
||||
echo "Restart production server..." >&2
|
||||
systemctl restart riju
|
|
@ -0,0 +1,12 @@
|
|||
[Unit]
|
||||
Description=Riju online coding sandbox
|
||||
Requires=docker.service
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
Type=exec
|
||||
ExecStart=riju
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"variables": {
|
||||
"docker_repo": "{{env `DOCKER_REPO`}}",
|
||||
"admin_password": "{{env `ADMIN_PASSWORD`}}",
|
||||
"admin_ssh_public_key_file": "{{env `ADMIN_SSH_PUBLIC_KEY_FILE`}",
|
||||
"deploy_ssh_public_key_file": "{{env `DEPLOY_SSH_PUBLIC_KEY_FILE`}"
|
||||
},
|
||||
"builders": [
|
||||
{
|
||||
"type": "amazon-ebs",
|
||||
"source_ami_filter": {
|
||||
"filters": {
|
||||
"virtualization-type": "hvm",
|
||||
"root-device-type": "ebs",
|
||||
"name": "ubuntu/images/ubuntu-groovy-20.10-amd64-server-*"
|
||||
},
|
||||
"owners": ["099720109477"],
|
||||
"most_recent": true
|
||||
},
|
||||
"instance_type": "t3.micro",
|
||||
"ssh_username": "ubuntu",
|
||||
"ami_name": "riju-{{timestamp}}"
|
||||
}
|
||||
],
|
||||
"provisioners": [
|
||||
{
|
||||
"type": "shell",
|
||||
"script": "validate.bash",
|
||||
"environment_vars": [
|
||||
"DOCKER_REPO={{user `docker_repo`}}",
|
||||
"ADMIN_PASSWORD={{user `admin_password`}}",
|
||||
"ADMIN_SSH_PUBLIC_KEY_FILE={{user `admin_ssh_public_key_file`}}",
|
||||
"DEPLOY_SSH_PUBLIC_KEY_FILE={{user `deploy_ssh_public_key_file`}}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"source": "riju",
|
||||
"destination": "/usr/local/bin/riju"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"source": "riju-deploy",
|
||||
"destination": "/usr/local/bin/riju-deploy"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"source": "riju.service",
|
||||
"destination": "/etc/systemd/system/riju.service"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"source": "{{user `admin_ssh_public_key_file`}}",
|
||||
"destination": "/tmp/id_admin.pub"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"source": "{{user `deploy_ssh_public_key_file`}}",
|
||||
"destination": "/tmp/id_deploy.pub"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"script": "provision.bash",
|
||||
"environment_vars": [
|
||||
"DOCKER_REPO={{user `docker_repo`}}",
|
||||
"ADMIN_PASSWORD={{user `admin_password`}}"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
: ${DOCKER_REPO}
|
||||
: ${ADMIN_PASSWORD}
|
||||
: ${ADMIN_SSH_PUBLIC_KEY_FILE}
|
||||
: ${DEPLOY_SSH_PUBLIC_KEY_FILE}
|
|
@ -19,7 +19,9 @@ for src in system/src/*.c; do
|
|||
out="${out/.c}"
|
||||
verbosely clang -Wall -Wextra -Werror -std=c11 "${src}" -o "${out}"
|
||||
if [[ "${out}" == *-privileged ]]; then
|
||||
sudo chown root:riju "${out}"
|
||||
if getent group riju >/dev/null; then
|
||||
sudo chown root:riju "${out}"
|
||||
fi
|
||||
sudo chmod a=,g=rx,u=rwxs "${out}"
|
||||
fi
|
||||
done
|
||||
|
|
28
tf/infra.tf
28
tf/infra.tf
|
@ -13,15 +13,37 @@ terraform {
|
|||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
tags = {
|
||||
Terraform = "Managed by Terraform"
|
||||
}
|
||||
}
|
||||
|
||||
data "external" "env" {
|
||||
program = ["jq", "-n", "env"]
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
profile = "default"
|
||||
region = "us-west-1"
|
||||
}
|
||||
|
||||
data "aws_region" "current" {}
|
||||
|
||||
resource "aws_s3_bucket" "riju_debs" {
|
||||
bucket = "riju-debs"
|
||||
acl = "public-read"
|
||||
tags = {
|
||||
Terraform = "Managed by Terraform"
|
||||
}
|
||||
tags = local.tags
|
||||
}
|
||||
|
||||
resource "aws_instance" "server" {
|
||||
instance_type = "t3.micro"
|
||||
ami = data.external.env.result.AMI_ID
|
||||
tags = local.tags
|
||||
}
|
||||
|
||||
resource "aws_ebs_volume" "data" {
|
||||
availability_zone = "${data.aws_region.current.name}a"
|
||||
size = 100
|
||||
tags = local.tags
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue