First commit

This commit is contained in:
Héctor Molinero Fernández 2019-02-20 23:10:38 +01:00
commit 3608dd8a31
11 changed files with 337 additions and 0 deletions

1
.dockerignore Normal file
View File

@ -0,0 +1 @@
/dist/

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/dist/

38
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,38 @@
image: docker:stable

services:
- docker:dind

stages:
- build:images
- push:images

variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2

build:image:
stage: build:images
before_script:
- docker info
- apk add --no-cache coreutils git make
script:
- make build-image save-image
artifacts:
expire_in: 1 hour
paths:
- dist/

push:image:
stage: push:images
before_script:
- apk add --no-cache coreutils git make
- docker login -u "${CI_DEPLOY_USER}" -p "${CI_DEPLOY_PASSWORD}" "${CI_REGISTRY}" >/dev/null 2>&1
script:
- make load-image push-image
only:
- /^v([0-9.]+)(-.+)?$/
except:
- branches
dependencies:
- build:image

48
Dockerfile Normal file
View File

@ -0,0 +1,48 @@
FROM ubuntu:18.04

# Environment
ENV QEMU_CPU=2
ENV QEMU_RAM=1024M
ENV QEMU_DISK_SIZE=16G
ENV QEMU_DISK_FORMAT=qcow2
ENV QEMU_KEYBOARD=en-us
ENV QEMU_KVM=false

# Install system packages
RUN export DEBIAN_FRONTEND=noninteractive \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
net-tools \
novnc \
qemu-kvm \
qemu-system-x86 \
qemu-utils \
runit \
unzip \
&& rm -rf /var/lib/apt/lists/*

# Create data directories
RUN mkdir -p /var/lib/qemu/images/ /var/lib/qemu/iso/

# Download ReactOS ISO
ARG REACTOS_ISO_URL=https://github.com/reactos/reactos/releases/download/0.4.10-release/ReactOS-0.4.10-iso.zip
ARG REACTOS_ISO_CHECKSUM=6e7b80a8d89adf1ed73a4733227d1ecf368bb237fafc322b9fb319a737dcd061
RUN mkdir /tmp/reactos/ \
&& curl -Lo /tmp/reactos/reactos.zip "${REACTOS_ISO_URL}" \
&& echo "${REACTOS_ISO_CHECKSUM} /tmp/reactos/reactos.zip" | sha256sum -c \
&& unzip /tmp/reactos/reactos.zip -d /tmp/reactos/ \
&& mv /tmp/reactos/*.iso /var/lib/qemu/iso/reactos.iso \
&& rm -rf /tmp/reactos/

# Copy services
COPY --chown=root:root scripts/service/ /etc/service/

# Copy scripts
COPY --chown=root:root scripts/bin/ /usr/local/bin/

# Expose noVNC port
EXPOSE 6080/tcp

CMD ["/usr/local/bin/docker-foreground-cmd"]

22
LICENSE.md Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
=====================

Copyright © 2019 Héctor Molinero Fernández

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

112
Makefile Normal file
View File

@ -0,0 +1,112 @@
#!/usr/bin/make -f

SHELL := /bin/sh
.SHELLFLAGS = -eu -c

DOCKER := $(shell command -v docker 2>/dev/null)
GIT := $(shell command -v git 2>/dev/null)

DISTDIR := ./dist

IMAGE_NAMESPACE := hectormolinero
IMAGE_NAME := qemu-reactos
IMAGE_VERSION := v0

# If git is available and the directory is a repository, use the latest tag as IMAGE_VERSION.
ifeq ([$(notdir $(GIT))][$(wildcard .git/.)],[git][.git/.])
IMAGE_VERSION := $(shell '$(GIT)' describe --abbrev=0 --tags 2>/dev/null || printf '%s' '$(IMAGE_VERSION)')
endif

IMAGE_LATEST_TAG := $(IMAGE_NAMESPACE)/$(IMAGE_NAME):latest
IMAGE_VERSION_TAG := $(IMAGE_NAMESPACE)/$(IMAGE_NAME):$(IMAGE_VERSION)

IMAGE_DOCKERFILE := ./Dockerfile
IMAGE_TARBALL := $(DISTDIR)/$(IMAGE_NAME).tgz

##################################################
## "all" target
##################################################

.PHONY: all
all: save-image

##################################################
## "build-*" targets
##################################################

.PHONY: build-image
build-image:
'$(DOCKER)' build \
--tag '$(IMAGE_LATEST_TAG)' \
--tag '$(IMAGE_VERSION_TAG)' \
--file '$(IMAGE_DOCKERFILE)' ./

##################################################
## "save-*" targets
##################################################

define save_image
'$(DOCKER)' save '$(1)' | gzip -n > '$(2)'
endef

.PHONY: save-image
save-image: $(IMAGE_TARBALL)

$(IMAGE_TARBALL): build-image
mkdir -p '$(DISTDIR)'
$(call save_image,$(IMAGE_VERSION_TAG),$@)

##################################################
## "load-*" targets
##################################################

define load_image
'$(DOCKER)' load -i '$(1)'
endef

define tag_image
'$(DOCKER)' tag '$(1)' '$(2)'
endef

.PHONY: load-image
load-image:
$(call load_image,$(IMAGE_TARBALL))
$(call tag_image,$(IMAGE_VERSION_TAG),$(IMAGE_LATEST_TAG))

##################################################
## "push-*" targets
##################################################

define push_image
'$(DOCKER)' push '$(1)'
endef

.PHONY: push-image
push-image:
$(call push_image,$(IMAGE_VERSION_TAG))
$(call push_image,$(IMAGE_LATEST_TAG))

##################################################
## "version" target
##################################################

.PHONY: version
version:
@if printf -- '%s' '$(IMAGE_VERSION)' | grep -q '^v[0-9]\{1,\}$$'; then \
NEW_IMAGE_VERSION=$$(awk -v 'v=$(IMAGE_VERSION)' 'BEGIN {printf "v%.0f", substr(v,2)+1}'); \
printf -- '%s\n' "$${NEW_IMAGE_VERSION}" > ./VERSION; \
'$(GIT)' add ./VERSION; '$(GIT)' commit -m "$${NEW_IMAGE_VERSION}"; \
'$(GIT)' tag -a "$${NEW_IMAGE_VERSION}" -m "$${NEW_IMAGE_VERSION}"; \
else \
>&2 printf -- 'Malformed version string: %s\n' '$(IMAGE_VERSION)'; \
exit 1; \
fi

##################################################
## "clean" target
##################################################

.PHONY: clean
clean:
rm -f '$(IMAGE_TARBALL)'
if [ -d '$(DISTDIR)' ]; then rmdir '$(DISTDIR)'; fi

37
README.md Normal file
View File

@ -0,0 +1,37 @@
# ReactOS on Docker

A Docker image for the [ReactOS](https://www.reactos.org) operating system.

## Start an instance
```sh
docker run --detach \
--name qemu-reactos \
--restart on-failure:3 \
--publish 127.0.0.1:6080:6080/tcp \
--privileged --env QEMU_KVM=true \
hectormolinero/qemu-reactos:latest
```
> The instance will be available through a web browser from: http://localhost:6080/vnc_auto.html

## Environment variables
#### `QEMU_CPU`
Number of cores the VM is permitted to use (`2` by default).

#### `QEMU_RAM`
Amount of memory the VM is permitted to use (`1024M` by default).

#### `QEMU_DISK_SIZE`
VM disk size (`16G` by default).

#### `QEMU_DISK_FORMAT`
VM disk format (`qcow2` by default).

#### `QEMU_KEYBOARD`
VM keyboard layout (`en-us` by default).

#### `QEMU_KVM`
Start QEMU in KVM mode (`false` by default).
> The `--privileged` option is required to use KVM in the container.

## License
See the [license](LICENSE.md) file.

44
run.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/sh

set -eu
export LC_ALL=C

DOCKER_IMAGE_NAMESPACE=hectormolinero
DOCKER_IMAGE_NAME=qemu-reactos
DOCKER_IMAGE_VERSION=latest
DOCKER_IMAGE=${DOCKER_IMAGE_NAMESPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION}
DOCKER_CONTAINER=${DOCKER_IMAGE_NAME}

imageExists() { [ -n "$(docker images -q "$1")" ]; }
containerExists() { docker ps -aqf name="$1" --format '{{.Names}}' | grep -Fxq "$1"; }
containerIsRunning() { docker ps -qf name="$1" --format '{{.Names}}' | grep -Fxq "$1"; }

if ! imageExists "${DOCKER_IMAGE}"; then
>&2 printf -- '%s\n' "${DOCKER_IMAGE} image doesn't exist!"
exit 1
fi

if containerIsRunning "${DOCKER_CONTAINER}"; then
printf -- '%s\n' "Stopping \"${DOCKER_CONTAINER}\" container..."
docker stop "${DOCKER_CONTAINER}" >/dev/null
fi

if containerExists "${DOCKER_CONTAINER}"; then
printf -- '%s\n' "Removing \"${DOCKER_CONTAINER}\" container..."
docker rm "${DOCKER_CONTAINER}" >/dev/null
fi

printf -- '%s\n' "Creating \"${DOCKER_CONTAINER}\" container..."
docker run --detach \
--name "${DOCKER_CONTAINER}" \
--hostname "${DOCKER_CONTAINER}" \
--restart on-failure:3 \
--log-opt max-size=32m \
--publish '127.0.0.1:5900:5900/tcp' \
--publish '127.0.0.1:6080:6080/tcp' \
--publish '127.0.0.1:15900:5900/tcp' \
--privileged --env QEMU_KVM=true \
"${DOCKER_IMAGE}" "$@" >/dev/null

printf -- '%s\n\n' 'Done!'
exec docker logs -f "${DOCKER_CONTAINER}"

View File

@ -0,0 +1,9 @@
#!/bin/sh

set -eu

# Create ReactOS disk
qemu-img create -f "${QEMU_DISK_FORMAT}" /var/lib/qemu/images/reactos.img "${QEMU_DISK_SIZE}"

# Start all services
exec runsvdir -P /etc/service/

7
scripts/service/novnc/run Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh

set -eu

cd ~/
exec 2>&1
exec /usr/share/novnc/utils/launch.sh --listen 6080 --vnc localhost:5900

18
scripts/service/qemu/run Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh

set -eu

QEMU=$(command -v qemu-system-x86_64)
QEMU_ARGS="${QEMU_ARGS-} -smp ${QEMU_CPU} -m ${QEMU_RAM}"
QEMU_ARGS="${QEMU_ARGS-} -vga std -display vnc=:0"
QEMU_ARGS="${QEMU_ARGS-} -drive file=/var/lib/qemu/images/reactos.img,index=0,media=disk,format=${QEMU_DISK_FORMAT}"
QEMU_ARGS="${QEMU_ARGS-} -drive file=/var/lib/qemu/iso/reactos.iso,index=2,media=cdrom,format=raw"
QEMU_ARGS="${QEMU_ARGS-} -boot order=cd,menu=on,splash-time=5000"
QEMU_ARGS="${QEMU_ARGS-} -netdev user,id=n0,hostfwd=tcp::13389-:3389,hostfwd=tcp::15900-:5900 -device rtl8139,netdev=n0"
QEMU_ARGS="${QEMU_ARGS-} -usb -device usb-tablet"
QEMU_ARGS="${QEMU_ARGS-} -k ${QEMU_KEYBOARD}"
if [ "${QEMU_KVM}" = true ]; then QEMU_ARGS="${QEMU_ARGS-} -enable-kvm"; fi

cd ~/
exec 2>&1
exec "${QEMU}" ${QEMU_ARGS}