diff --git a/.env b/.env new file mode 100644 index 0000000..bc0a488 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +CONTAINER_ENGINE=docker \ No newline at end of file diff --git a/.github/workflows/container-build.yml b/.github/workflows/container-build.yml new file mode 100644 index 0000000..e748ac0 --- /dev/null +++ b/.github/workflows/container-build.yml @@ -0,0 +1,42 @@ +name: Build teams container +on: + - push + +jobs: + build: + name: Build image + runs-on: ubuntu-latest + env: + IMAGE_NAME: teams-desktop + REGISTRY: ghcr.io/christoffernissen + steps: + + - name: Clone the repository + uses: actions/checkout@v2 + + - name: Buildah Action + id: build-image + uses: redhat-actions/buildah-build@v2 + with: + image: ${{ env.IMAGE_NAME }} + tags: latest ${{ github.sha }} + containerfiles: | + ./Containerfile + + - name: Log in to the GitHub Container registry + uses: redhat-actions/podman-login@v1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Push to GitHub Container Repository + id: push-to-ghcr + uses: redhat-actions/push-to-registry@v2 + with: + image: ${{ steps.build-image.outputs.image }} + tags: ${{ steps.build-image.outputs.tags }} + registry: ${{ env.REGISTRY }} + + - name: Print image URL + run: echo "Image pushed to ${{ steps.push-to-ghcr.outputs.registry-paths }}" \ No newline at end of file diff --git a/.gitigore b/.gitigore new file mode 100644 index 0000000..6dd29b7 --- /dev/null +++ b/.gitigore @@ -0,0 +1 @@ +bin/ \ No newline at end of file diff --git a/Dockerfile b/Containerfile similarity index 100% rename from Dockerfile rename to Containerfile diff --git a/Makefile b/Makefile index bed7b04..c6f2659 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,35 @@ +include .env + launch: teams-wrapper teams teams-wrapper-two teams kill-containers: - docker kill teams || docker kill teams-two # if error try kill other instance before exit - docker kill teams-two + ${CONTAINER_ENGINE} kill teams || podman kill teams-two # if error try kill other instance before exit + ${CONTAINER_ENGINE} kill teams-two build: - docker build . -t stifstof/teams-desktop:latest + ${CONTAINER_ENGINE} build -t docker.io/stifstof/teams-desktop:latest -f Containerfile . + +build-no-cache: + ${CONTAINER_ENGINE} build --no-cache -t docker.io/stifstof/teams-desktop:latest -f Containerfile . install: - docker run -it --rm \ - --volume /usr/local/bin:/target \ - stifstof/teams-desktop:latest install + ${CONTAINER_ENGINE} run -it --rm --privileged \ + --volume ./bin:/target \ + docker.io/stifstof/teams-desktop:latest install uninstall: - docker run -it --rm \ - --volume /usr/local/bin:/target \ - stifstof/teams-desktop:latest uninstall + ${CONTAINER_ENGINE} run -it --rm --privileged \ + --volume ./bin:/target \ + docker.io/stifstof/teams-desktop:latest uninstall # convenience jobs +push: + echo ${DOCKERHUB_STIFSTOF_PW} | podman login docker.io -u stifstof --password-stdin + ${CONTAINER_ENGINE} push docker.io/stifstof/teams-desktop:latest + reinstall: make uninstall make build @@ -28,4 +37,20 @@ reinstall: create-empty-config-folders: mkdir ~/.config/Microsoft - mkdir ~/.config/MicrosoftTwo \ No newline at end of file + mkdir ~/.config/MicrosoftTwo + +# system setup + +add-to-path: + export PATH=$PATH:/home/cn/Documents/git/TeamsInDocker/bin + +podman: + rm -f .env + echo "CONTAINER_ENGINE=podman" >> .env + +docker: + rm -f .env + echo "CONTAINER_ENGINE=docker" >> .env + +current_runtime: + cat .env \ No newline at end of file diff --git a/README.md b/README.md index dc8e4f7..5ea145f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,16 @@ -# Microsoft Teams in Docker +# Microsoft Teams in Container ![](https://i.imgur.com/pVwxCtz.png) +This projects objective is to provide Microsoft Teams as a container to enable multiple accounts to be used simultaniously. -This projects objective is to provide Microsoft Teams as a docker image to enable multiple accounts to be used simultaniously. +Currently the project supports Docker and Podman. Select which runtime you want with the convenient make targets: + +Makefile (System setup) +- docker +- podman +- current_runtime + +The default runtime is Docker. Select podman with "make podman" and confirm with "make current_runtime". The Makefile contains the relevant commands to use the application. The project works with two accounts, but can be extended to any number of accounts (not tested). @@ -45,6 +53,3 @@ Simply run make kill-containers make uninstall ``` - -Remmember to kill the containers with - diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..eee79c8 --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1 @@ +teams-* \ No newline at end of file diff --git a/docker-scripts/entrypoint.sh b/docker-scripts/entrypoint.sh index a71a357..6bbdde0 100755 --- a/docker-scripts/entrypoint.sh +++ b/docker-scripts/entrypoint.sh @@ -11,16 +11,12 @@ install_teams_desktop() { echo "Installing teams-wrapper..." install -m 0755 /var/cache/teams/teams-wrapper /target/ install -m 0755 /var/cache/teams/teams-wrapper-two /target/ - echo "Installing teams..." - ln -sf teams-wrapper /target/teams } uninstall_teams_desktop() { echo "Uninstalling teams-wrapper..." rm -rf /target/teams-wrapper rm -rf /target/teams-wrapper-two - echo "Uninstalling teams..." - rm -rf /target/teams } create_user() { @@ -54,9 +50,10 @@ grant_access_to_video_devices() { launch_teams_desktop() { cd /home/${TEAMS_DESKTOP_USER} - sudo -HEu ${TEAMS_DESKTOP_USER} PULSE_SERVER=/run/pulse/native $@ + sudo -u ${TEAMS_DESKTOP_USER} teams # exec sudo -HEu ${TEAMS_DESKTOP_USER} PULSE_SERVER=/run/pulse/native QT_GRAPHICSSYSTEM="native" $@ tail -f /home/${TEAMS_DESKTOP_USER}/.config/Microsoft/Microsoft\ Teams/logs/teams-startup.log + stat /home/${TEAMS_DESKTOP_USER}/.config/Microsoft/Microsoft\ Teams/logs/teams-startup.log } case "$1" in diff --git a/host-scripts/teams-wrapper b/host-scripts/teams-wrapper index 531925a..7c62d81 100755 --- a/host-scripts/teams-wrapper +++ b/host-scripts/teams-wrapper @@ -4,28 +4,34 @@ SCRIPT_NAME="teams-wrapper" LOCAL_COMPUTER_USERNAME=$(whoami) -# Docker config -IMAGE_NAME="stifstof/teams-desktop:latest" +# registry config +IMAGE_NAME="docker.io/stifstof/teams-desktop:latest" CONTAINER_NAME="teams" CONFIG_PATH="${HOME}/.config/Microsoft" - - - +# Container runtime (docker or podman) +CONTAINER_ENGINE="${CONTAINER_ENGINE}" +if [ -z "$CONTAINER_ENGINE" ] +then + echo "\$CONTAINER_ENGINE is empty. Defaulting to podman" + CONTAINER_ENGINE="podman" +fi ########## Script -PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +PATH=/home/cn/Documents/git/TeamsInDocker/bin:/usr/sbin:/usr/bin:/sbin:/bin TEAMS_DESKTOP_USER=${LOCAL_COMPUTER_USERNAME} +XSOCK=/home/$TEAMS_DESKTOP_USER/X/teamsOne/.X11-unix +XAUTH=/home/$TEAMS_DESKTOP_USER/X/teamsOne/."${CONTAINER_ENGINE}".xauth -# do we need to use sudo to start docker containers? -(id -Gn | grep -q docker) || SUDO=sudo +# do we need to use sudo to start containers? +if [ "$CONTAINER_ENGINE" == "docker" ]; then +(id -Gn | grep -q $CONTAINER_ENGINE) || SUDO=sudo +fi USER_UID=$(id -u) USER_GID=$(id -g) -XSOCK=/tmp/.X11-unix-teamsOne -XAUTH=/tmp/.docker.xauth-teamsOne DOWNLOAD_DIR=$(xdg-user-dir DOWNLOAD) if [ -z "${DOWNLOAD_DIR}" ]; then @@ -35,26 +41,29 @@ fi list_commands() { echo "" echo "Launch teams using:" - echo " teams OR " echo " teams-wrapper teams" echo "" exit 1 } cleanup_stopped_teams_desktop_instances() { - echo "Cleaning up stopped teams-desktop instances..." - for c in $(${SUDO} docker ps -a -q); do - image="$(${SUDO} docker inspect -f {{.Config.Image}} ${c})" - if [ "${image}" == ${IMAGE_NAME} ]; then - running=$(${SUDO} docker inspect -f {{.State.Running}} ${c}) + echo "Cleaning up stopped teams instances..." + for c in $(${SUDO} ${CONTAINER_ENGINE} ps -a -q); do + image="$(${SUDO} ${CONTAINER_ENGINE} inspect -f {{.Name}} ${c})" + if [ "${image}" == "${CONTAINER_NAME}" ]; then + running=$(${SUDO} ${CONTAINER_ENGINE} inspect -f {{.State.Running}} ${c}) if [ "${running}" != "true" ]; then - ${SUDO} docker rm "${c}" >/dev/null + ${SUDO} ${CONTAINER_ENGINE} rm "${c}" >/dev/null + fi + if [ "${running}" == "true" ]; then + ${SUDO} ${CONTAINER_ENGINE} kill "${c}" >/dev/null + ${SUDO} ${CONTAINER_ENGINE} rm "${c}" >/dev/null fi fi done } -prepare_docker_env_parameters() { +prepare_container_env_parameters() { ENV_VARS+=" --env=USER_UID=${USER_UID}" ENV_VARS+=" --env=USER_GID=${USER_GID}" ENV_VARS+=" --env=DISPLAY=unix$DISPLAY" @@ -63,8 +72,18 @@ prepare_docker_env_parameters() { ENV_VARS+=" --env=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket" } -prepare_docker_volume_parameters() { +create_x_folder() { + mkdir "/home/$TEAMS_DESKTOP_USER/X/teamsOne/" touch ${XAUTH} + touch ${XSOCK} +} + +prepare_container_volume_parameters() { + if [ -d "/home/$TEAMS_DESKTOP_USER/X/teamsOne/" ]; then + rm -rf "/home/$TEAMS_DESKTOP_USER/X/teamsOne/" + fi + create_x_folder + xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f ${XAUTH} nmerge - VOLUMES+=" --volume=${CONFIG_PATH}:/home/${TEAMS_DESKTOP_USER}/.config/Microsoft/" @@ -79,7 +98,7 @@ prepare_docker_volume_parameters() { } -prepare_docker_device_parameters() { +prepare_container_device_parameters() { # enumerate video devices for webcam support VIDEO_DEVICES= for device in /dev/video*; do @@ -109,24 +128,21 @@ elif [[ -n ${exec} ]]; then fi cleanup_stopped_teams_desktop_instances -prepare_docker_env_parameters -prepare_docker_volume_parameters -prepare_docker_device_parameters +prepare_container_env_parameters +prepare_container_volume_parameters +prepare_container_device_parameters echo "Starting ${prog}..." -${SUDO} docker run -d \ +set -o xtrace +${SUDO} ${CONTAINER_ENGINE} run -d \ --name ${CONTAINER_NAME} \ --network host \ - --privileged \ - --memory=8g \ - --shm-size=8g \ + --memory=4g \ + --shm-size=4g \ --device /dev/dri \ --device /dev/snd \ - --cap-add=SYS_ADMIN \ - -v /tmp/.X11-unix:/tmp/.X11-unix \ - -e DISPLAY=unix$DISPLAY \ ${ENV_VARS} \ ${VIDEO_DEVICES} \ ${VOLUMES} \ - ${TEAMS_EXTRA_DOCKER_ARGUMENTS} \ - ${IMAGE_NAME} ${prog} $@ >/dev/null \ No newline at end of file + ${TEAMS_EXTRA_CONTAINER_ARGUMENTS} \ + ${IMAGE_NAME} ${prog} $@ >/dev/null diff --git a/host-scripts/teams-wrapper-two b/host-scripts/teams-wrapper-two index 6268792..96993fd 100644 --- a/host-scripts/teams-wrapper-two +++ b/host-scripts/teams-wrapper-two @@ -4,28 +4,34 @@ SCRIPT_NAME="teams-wrapper-two" LOCAL_COMPUTER_USERNAME=$(whoami) -# Docker config -IMAGE_NAME="stifstof/teams-desktop:latest" +# config +IMAGE_NAME="docker.io/stifstof/teams-desktop:latest" CONTAINER_NAME="teams-two" CONFIG_PATH="${HOME}/.config/MicrosoftTwo" - - - +# Container runtime (docker or podman) +CONTAINER_ENGINE="${CONTAINER_ENGINE}" +if [ -z "$CONTAINER_ENGINE" ] +then + echo "\$CONTAINER_ENGINE is empty. Defaulting to podman" + CONTAINER_ENGINE="podman" +fi ########## Script -PATH=/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +PATH=/home/cn/Documents/git/TeamsInDocker/bin:/usr/sbin:/usr/bin:/sbin:/bin TEAMS_DESKTOP_USER=${LOCAL_COMPUTER_USERNAME} +XSOCK=/home/$TEAMS_DESKTOP_USER/X/teamsTwo/.X11-unix +XAUTH=/home/$TEAMS_DESKTOP_USER/X/teamsTwo/."${CONTAINER_ENGINE}".xauth # do we need to use sudo to start docker containers? -(id -Gn | grep -q docker) || SUDO=sudo +if [ "$CONTAINER_ENGINE" == "docker" ]; then +(id -Gn | grep -q $CONTAINER_ENGINE) || SUDO=sudo +fi USER_UID=$(id -u) USER_GID=$(id -g) -XSOCK=/tmp/.X11-unix-teamsTwo -XAUTH=/tmp/.docker.xauth-teamsTwo DOWNLOAD_DIR=$(xdg-user-dir DOWNLOAD) if [ -z "${DOWNLOAD_DIR}" ]; then @@ -35,26 +41,29 @@ fi list_commands() { echo "" echo "Launch teams using:" - echo " teams OR " echo " teams-wrapper teams" echo "" exit 1 } cleanup_stopped_teams_desktop_instances() { - echo "Cleaning up stopped teams-desktop instances..." - for c in $(${SUDO} docker ps -a -q); do - image="$(${SUDO} docker inspect -f {{.Config.Image}} ${c})" - if [ "${image}" == ${IMAGE_NAME} ]; then - running=$(${SUDO} docker inspect -f {{.State.Running}} ${c}) + echo "Cleaning up stopped teams instances..." + for c in $(${SUDO} ${CONTAINER_ENGINE} ps -a -q); do + image="$(${SUDO} ${CONTAINER_ENGINE} inspect -f {{.Name}} ${c})" + if [ "${image}" == "${CONTAINER_NAME}" ]; then + running=$(${SUDO} ${CONTAINER_ENGINE} inspect -f {{.State.Running}} ${c}) if [ "${running}" != "true" ]; then - ${SUDO} docker rm "${c}" >/dev/null + ${SUDO} ${CONTAINER_ENGINE} rm "${c}" >/dev/null + fi + if [ "${running}" == "true" ]; then + ${SUDO} ${CONTAINER_ENGINE} kill "${c}" >/dev/null + ${SUDO} ${CONTAINER_ENGINE} rm "${c}" >/dev/null fi fi done } -prepare_docker_env_parameters() { +prepare_container_env_parameters() { ENV_VARS+=" --env=USER_UID=${USER_UID}" ENV_VARS+=" --env=USER_GID=${USER_GID}" ENV_VARS+=" --env=DISPLAY=unix$DISPLAY" @@ -63,8 +72,18 @@ prepare_docker_env_parameters() { ENV_VARS+=" --env=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket" } -prepare_docker_volume_parameters() { +create_x_folder() { + mkdir "/home/$TEAMS_DESKTOP_USER/X/teamsTwo/" touch ${XAUTH} + touch ${XSOCK} +} + +prepare_container_volume_parameters() { + if [ -d "/home/$TEAMS_DESKTOP_USER/X/teamsTwo/" ]; then + rm -rf "/home/$TEAMS_DESKTOP_USER/X/teamsTwo/" + fi + create_x_folder + xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f ${XAUTH} nmerge - VOLUMES+=" --volume=${CONFIG_PATH}:/home/${TEAMS_DESKTOP_USER}/.config/Microsoft/" @@ -79,7 +98,7 @@ prepare_docker_volume_parameters() { } -prepare_docker_device_parameters() { +prepare_container_device_parameters() { # enumerate video devices for webcam support VIDEO_DEVICES= for device in /dev/video*; do @@ -109,24 +128,21 @@ elif [[ -n ${exec} ]]; then fi cleanup_stopped_teams_desktop_instances -prepare_docker_env_parameters -prepare_docker_volume_parameters -prepare_docker_device_parameters +prepare_container_env_parameters +prepare_container_volume_parameters +prepare_container_device_parameters echo "Starting ${prog}..." -${SUDO} docker run -d \ +set -o xtrace +${SUDO} ${CONTAINER_ENGINE} run -d \ --name ${CONTAINER_NAME} \ --network host \ - --privileged \ - --memory=8g \ - --shm-size=8g \ + --memory=4g \ + --shm-size=4g \ --device /dev/dri \ --device /dev/snd \ - --cap-add=SYS_ADMIN \ - -v /tmp/.X11-unix:/tmp/.X11-unix \ - -e DISPLAY=unix$DISPLAY \ ${ENV_VARS} \ ${VIDEO_DEVICES} \ ${VOLUMES} \ - ${TEAMS_EXTRA_DOCKER_ARGUMENTS} \ - ${IMAGE_NAME} ${prog} $@ >/dev/null \ No newline at end of file + ${TEAMS_EXTRA_CONTAINER_ARGUMENTS} \ + ${IMAGE_NAME} ${prog} $@ >/dev/null