Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@

# Additional .npmignore entries (not in .gitignore)
/test
/docker-image
3 changes: 3 additions & 0 deletions docker-image/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test/
.pytest_cache/
.idea
3 changes: 3 additions & 0 deletions docker-image/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.pytest_cache/
__pycache__
data/
33 changes: 33 additions & 0 deletions docker-image/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# How to contribute

If you want to experiment with the image and/or contribute to its development,
please read this document.

## Run tests

```bash
make test
```

The first run might take a while, since the image has to be build. Follow up test runs will be faster.

## Start & stop locally

Build and run a local container named solid-server via

```bash
make start
```

and stop it via

```bash
make stop
```

## Inspect & debug

To start a shell in a running container (started with `make start`) run `make attach`.

To just run a shell in the built image (without starting solid) run `make inspect`.

31 changes: 31 additions & 0 deletions docker-image/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
test: ## run testinfra tests against the project
docker run --rm -t \
-v $(shell pwd):/project \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
aveltens/docker-testinfra

lint: ## run hadolint against the Dockerfile
docker run --rm -i hadolint/hadolint < src/Dockerfile

build: ## build the docker image
cd src && docker build --tag nodesolidserver/node-solid-server .

inspect: build ## run a shell in the docker image
docker run --rm -it --entrypoint sh nodesolidserver/node-solid-server

start: build ## start solid-server docker container
docker run --rm \
-it -d \
-p 8443:8443 \
-u "$(id -u):$(id -g)" \
-v $(shell pwd)/data:/opt/solid/data \
--name solid-server \
nodesolidserver/node-solid-server

stop: ## stop the solid-server docker container
docker stop solid-server

attach: ## execute a shell in the running solid-server docker container
docker exec -it solid-server sh

.PHONY: test build inspect run attach
51 changes: 51 additions & 0 deletions docker-image/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# NSS Docker image

Containerized version of node-solid-server

## How to use

For quickly trying out this image or solid-server in general you can run:
```bash
docker run -p 8443:8443 nodesolidserver/node-solid-server
```

You will be able to access the server via `https://localhost:8443` then. It will use auto-generated self-signed certificates and is **not suited for production use**. For a production server you will have to create some real certificates and configure environment variables, like SOLID_SERVER_URI, SOLID_SSL_KEY and SOLID_SSL_CERT. Take a look at the examples folder [at GitHub](https://github.com/angelo-v/docker-solid-server/tree/master/examples) for details.

### Environment variables

All solid configuration flags can be set by an equivalent environment variable.
The official solid-server documentation
[explains them in detail](https://github.com/solid/node-solid-server#extra-flags-expert).

### Docker compose

For a productive setup you may want to use docker-compose. Example setups can be found
in the [examples folder](https://github.com/angelo-v/docker-solid-server/tree/master/examples). Here is an overview of what is in there:

#### Simple setup without proxy

`./examples/docker-compose.simple.yml`

Run solid-server directly on HTTPS port 443 without a proxy in between.
You will need to have your certificates ready and mount them into the container.

#### Running solid behind nginx proxy

`./examples/docker-compose.nginx.yml`

Run solid-server on port 8443 behind a nginx proxy on 443. You will need to setup an nginx container with letsencrypt companion [as described here](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion).

#### Other setups

The setup you need is not presented here? Feel free to ask, or provide a Pull Request
with your solution.

## Feedback & Discussion

There is a [topic in the Solid Forum](https://forum.solidproject.org/t/official-solid-docker-image/748/5),
you are welcome to join in.

## Contributing

If you would like to contribute to the development of this image,
see [CONTRIBUTING.md](./CONTRIBUTING.md)
50 changes: 50 additions & 0 deletions docker-image/examples/docker-compose.nginx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# This example assumes, that you are running a jwilders/nginx proxy
# with certificate generation by a letsencrypt companion container
# as described here:
#
# https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/blob/master/docs/Docker-Compose.md
#
# This should provide a docker volume containing the generated certificates.
# We will use the same cert and key as the webproxy for the actual solid server. While it seems to
# work, I am not sure if it is actually a good idea. Please file an issue if you want to discuss this.

# Adjust any line that is commented with (!):
# 1. Change any occurrence of the domain `solid.example` to your actual domain
# 2. Adjust the `latest` tag to a specific version you want to use.

version: '3.7'
services:
server:
image: nodesolidserver/node-solid-server:latest # (!) use specific version tag here

# this ensures automatic container start, when host reboots
restart: always

expose:
- 8443

volumes:
# mount local directories to the container
# (!) the host directories have to exist and be owned by UID 1000
- /opt/solid/data:/opt/solid/data
- /opt/solid/.db:/opt/solid/.db
- /opt/solid/config:/opt/solid/config
- nginxproxy_certs:/opt/solid/certs

environment:
# (!) use your actual SOLID_SERVER_URI
- "SOLID_SERVER_URI=https://solid.example"
# (!) adjust path to the letsencrypt key and cert
- "SOLID_SSL_KEY=/opt/solid/certs/solid.example/key.pem"
- "SOLID_SSL_CERT=/opt/solid/certs/solid.example/fullchain.pem"
# (!) use your actual host name
- "VIRTUAL_HOST=solid.example"
- "VIRTUAL_PORT=8443"
- "VIRTUAL_PROTO=https"
# (!) use your actual host name
- "LETSENCRYPT_HOST=solid.example"
- "[email protected]"
volumes:
# (!) mount certificates from an external volume from your nginx setup
nginxproxy_certs:
external: true
34 changes: 34 additions & 0 deletions docker-image/examples/docker-compose.simple.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This file is an example for running solid server directly on port 443 with
# existing (letsencrypt) certificates and without reverse proxy.

# To use it adjust any line that is commented with (!):
# 1. Change any occurrence of the domain `solid.example` to your actual domain
# 2. Adjust the `latest` tag to a specific version you want to use.

version: '3.7'
services:
server:
image: nodesolidserver/node-solid-server:latest # (!) use specific version tag here

# this ensures automatic container start, when host reboots
restart: always

ports:
- 443:8443

volumes:
# mount local directories to the container
# (!) the host directories have to exist and be owned by UID 1000
- /opt/solid/data:/opt/solid/data
- /opt/solid/.db:/opt/solid/.db
- /opt/solid/config:/opt/solid/config

# (!) mount existing TLS certificates, e.g. from letsencrypt
# (!) ensure that the key and fullchain files are readable by UID 1000
- /etc/letsencrypt/live/solid.example/:/opt/solid/certs

environment:
# (!) use your actual SOLID_SERVER_URI
- "SOLID_SERVER_URI=https://solid.example"
- "SOLID_SSL_KEY=/opt/solid/certs/key.pem"
- "SOLID_SSL_CERT=/opt/solid/certs/fullchain.pem"
33 changes: 33 additions & 0 deletions docker-image/src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM node:10-alpine

RUN apk add --no-cache openssl

ARG SOLID_SERVER_VERSION=latest
RUN npm install -g solid-server@${SOLID_SERVER_VERSION}

# image configuration
ENV SOLID_HOME=/opt/solid
ENV PROCESS_USER=node
ENV TEMPORARY_CERT_NAME=solid-temporary

WORKDIR ${SOLID_HOME}
COPY ./entrypoint.sh ./entrypoint.sh
COPY ./checks.sh ./checks.sh
COPY ./create-temporary-cert.sh ./create-temporary-cert.sh
RUN chown --recursive ${PROCESS_USER}:${PROCESS_USER} ${SOLID_HOME}

USER ${PROCESS_USER}

# solid configuration
ENV SOLID_ROOT=${SOLID_HOME}/data
ENV SOLID_SSL_KEY=${SOLID_HOME}/${TEMPORARY_CERT_NAME}.key
ENV SOLID_SSL_CERT=${SOLID_HOME}/${TEMPORARY_CERT_NAME}.crt
ENV SOLID_PORT=8443
ENV SOLID_CORS_PROXY=/xss
ENV DEBUG=solid:*

VOLUME $SOLID_HOME

ENTRYPOINT ["./entrypoint.sh"]

CMD ["start"]
56 changes: 56 additions & 0 deletions docker-image/src/checks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/sh

echo "checking preconditions..."

checks_failed=0

check_failed()
{
checks_failed=$((checks_failed + 1))
}
check_if_writable()
{
# checks if the given dir is writable, if it exists
# it's ok if the dir does not exist at all, because it will be created
# during solid server startup then and have the correct permissions
dir=$1
if [ -d "${dir}" ]; then
if [ -w "${dir}" ]; then
echo "✓ ${dir} is accessible by $(whoami)"
else
echo "✗ ${dir} not writable by $(whoami)"
check_failed
fi
fi
}

check_if_file_readable()
{
# checks if the given file exists and is readable
file=$1
if [ -e "${file}" ]; then
if [ -r "${file}" ]; then
echo "✓ ${file} is accessible by $(whoami)"
else
echo "✗ ${file} not readable by $(whoami)"
check_failed
fi
else
echo "✗ ${file} does not exist"
check_failed
fi
}

check_if_writable "${SOLID_HOME}/config"
check_if_writable "${SOLID_HOME}/data"
check_if_writable "${SOLID_HOME}/.db"
check_if_file_readable "${SOLID_SSL_KEY}"
check_if_file_readable "${SOLID_SSL_CERT}"

if [ "$checks_failed" -gt 0 ]; then
echo "Finished: ERROR"
exit 1
else
echo "Finished: SUCCESS"
exit 0;
fi
14 changes: 14 additions & 0 deletions docker-image/src/create-temporary-cert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh
set -e

NAME=$1

if [ -z $NAME ]; then
echo "Usage: ./create-temporary-cert.sh some-name"
exit 1
fi

openssl req -nodes -x509 -days 3 -newkey rsa:2048 \
-keyout ./$NAME.key \
-out ./$NAME.crt \
-subj "/O=$NAME/OU=$NAME/CN=$NAME"
8 changes: 8 additions & 0 deletions docker-image/src/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh

set -e

./create-temporary-cert.sh ${TEMPORARY_CERT_NAME}
./checks.sh

solid "$@"
9 changes: 9 additions & 0 deletions docker-image/src/hooks/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

# conditional assignment of SOLID_SERVER_VERSION, like
# SOLID_SERVER_VERSION = $SOURCE_BRANCH == master ? 'latest' : $SOURCE_BRANCH
SOLID_SERVER_VERSION=latest && [[ "$SOURCE_BRANCH" != "master" ]] && SOLID_SERVER_VERSION=${SOURCE_BRANCH}

echo building on branch/tag ${SOURCE_BRANCH}, server version ${SOLID_SERVER_VERSION} with image name ${IMAGE_NAME} .

docker build --build-arg SOLID_SERVER_VERSION=${SOLID_SERVER_VERSION} --file Dockerfile -t ${IMAGE_NAME} .
11 changes: 11 additions & 0 deletions docker-image/test/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import docker
import pytest

@pytest.fixture(scope="session")
def client():
return docker.from_env()

@pytest.fixture(scope="session")
def image(client):
img, _ = client.images.build(path='./src', dockerfile='Dockerfile')
return img
Loading