{"id":23370134,"url":"https://github.com/maastrichtu-ids/get-started-with-docker","last_synced_at":"2026-05-04T07:39:47.200Z","repository":{"id":92532378,"uuid":"315262462","full_name":"MaastrichtU-IDS/get-started-with-docker","owner":"MaastrichtU-IDS","description":"🐳 A straightforward workshop to get started with Docker in an hour","archived":false,"fork":false,"pushed_at":"2020-11-25T12:33:55.000Z","size":112,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-08T00:41:40.503Z","etag":null,"topics":["docker","docker-compose","workshop"],"latest_commit_sha":null,"homepage":"","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaastrichtU-IDS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-23T09:25:09.000Z","updated_at":"2020-11-27T22:09:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"8e288a09-90db-4562-a58e-fc1012fbf3fc","html_url":"https://github.com/MaastrichtU-IDS/get-started-with-docker","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MaastrichtU-IDS/get-started-with-docker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaastrichtU-IDS%2Fget-started-with-docker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaastrichtU-IDS%2Fget-started-with-docker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaastrichtU-IDS%2Fget-started-with-docker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaastrichtU-IDS%2Fget-started-with-docker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaastrichtU-IDS","download_url":"https://codeload.github.com/MaastrichtU-IDS/get-started-with-docker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaastrichtU-IDS%2Fget-started-with-docker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32599408,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","workshop"],"created_at":"2024-12-21T15:34:07.360Z","updated_at":"2026-05-04T07:39:47.183Z","avatar_url":"https://github.com/MaastrichtU-IDS.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Get started with Docker containers 🐳\n\nA workshop to get started with Docker in an hour 🕐 (hopefully)!\n\nDuring this workshop, you will:\n\n* Find and run a Docker image for a database service (a Virtuoso triplestore for RDF data)\n* Define a `docker-compose.yml` file to run a JupyterLab container alongside the database\n* Customize an existing image by installing new packages and changing the user (JupyterLab)\n* Login to DockerHub and GitHub Container Registry.\n\nPrerequisites:\n\n* [Docker](https://docs.docker.com/get-docker/) installed\n  \n  * If you use Windows 🏢, we recommend you to use Docker with [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10)\n  * If you use Linux 🐧, you will need to make sure you have also [`docker-compose` installed](https://docs.docker.com/compose/install/)\n  \n* Fundamental knowledge of how to navigate in the terminal ⌨️\n  1. **L**i**s**t files in current directory: `ls`\n  2. Find the **P**ath to the (current) **W**orking **D**irectory: `pwd`\n  3. **C**hange **D**irectory: `cd subfolder` or `cd ../parent-folder`\n  4. Use the `tab` key in your terminal to get recommendations for potential command arguments (later [install ZSH](https://ohmyz.sh/) for a better experience in the computer terminal)\n\n  \u003e When defining a path, the dot `.` represents the current directory, it is usually used at the start of the path, e.g. `./data` for the data folder in the current directory)\n  \u003e\n  \u003e N.B.: folder and directory usually mean the same thing.\n\n## Table of Content 🧭\n\n* [Get the workshop files \u003cg-emoji class=\"g-emoji\" alias=\"inbox_tray\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4e5.png\"\u003e📥\u003c/g-emoji\u003e](#get-the-workshop-files-)\n* [Task 1: Find and start a database container \u003cg-emoji class=\"g-emoji\" alias=\"mag_right\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f50e.png\"\u003e🔎\u003c/g-emoji\u003e](#task-1-find-and-start-a-database-container-)\n* [Task 2: Start the database container with a docker-compose file \u003cg-emoji class=\"g-emoji\" alias=\"clipboard\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4cb.png\"\u003e📋\u003c/g-emoji\u003e](#task-2-start-the-database-container-with-a-docker-compose-file-)\n* [Task 3: Add JupyterLab to the docker-compose \u003cg-emoji class=\"g-emoji\" alias=\"telescope\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f52d.png\"\u003e🔭\u003c/g-emoji\u003e](#task-3-add-jupyterlab-to-the-docker-compose-)\n* [Task 4: Customize the Docker image \u003cg-emoji class=\"g-emoji\" alias=\"package\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4e6.png\"\u003e📦\u003c/g-emoji\u003e](#task-4-customize-the-docker-image-)\n* [Task 5: Login to Container Registries \u003cg-emoji class=\"g-emoji\" alias=\"key\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f511.png\"\u003e🔑\u003c/g-emoji\u003e](#task-5-login-to-container-registries-)\n    * [Login to DockerHub](#login-to-dockerhub)\n    * [Login to GitHub Container Registry](#login-to-github-container-registry)\n* [Bonus: Publish your image \u003cg-emoji class=\"g-emoji\" alias=\"loudspeaker\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/1f4e2.png\"\u003e📢\u003c/g-emoji\u003e](#bonus-publish-your-image-)\n    * [Publish to GitHub Container Registry](#publish-to-github-container-registry)\n    * [Publish to DockerHub](#publish-to-dockerhub)\n    * [Use automated workflows](#use-automated-workflows)\n* [Check the solution \u003cg-emoji class=\"g-emoji\" alias=\"heavy_check_mark\" fallback-src=\"https://github.githubassets.com/images/icons/emoji/unicode/2714.png\"\u003e✔️\u003c/g-emoji\u003e](#use-automated-workflows)\n\n## Get the workshop files 📥\n\nUse `git` to clone the repository.\n\n1. Open your terminal ⌨️\n2. Go to the directory where you want to store the workshop folder (using `cd my-folder/`)\n3. Clone the GitHub repository with this command:\n\n```shell\ngit clone https://github.com/MaastrichtU-IDS/get-started-with-docker\n```\n\n\u003e If you don't have `git` installed you can also [download the workshop as a `.zip` file](https://github.com/MaastrichtU-IDS/get-started-with-docker/archive/master.zip) and unzip it 🤐\n\n4. **Go the workshop folder in your terminal**:\n\n```shell\ncd get-started-with-docker\n```\n\n\u003e For the whole workshop we assume you are running the terminal commands from this directory.\n\n---\n\n## Task 1: Find and start a database container 🔎\n\nWe want to start the [OpenLink Virtuoso database](http://vos.openlinksw.com/owiki/wiki/VOS) (a triplestore for RDF data) without losing time installing all the required packages and setting up the configuration. \n\nWe will then use a Docker container:\n\n1. 🔎 Search for [**\"virtuoso docker\" on Google**](https://www.google.com/search?q=virtuoso+docker) (or your favourite search engine).\n\n2. Different Docker images will be found. Here are a few bits of advice to pick the right Docker image for a service:\n\n    * Check for a **recent image** that seems to be kept up-to-date, with an active community, or company behind if possible\n    * Check the number of **Pulls** (downloads) to see how popular it is\n    * You can also check how the application is installed in the `Dockerfile` (when source code available)\n    * Note that currently, most existing images are available on DockerHub, but things are changing (quay.io, ghcr.io...). Thankfully, using an image from a different registry does not change anything else than the image name!\n\n3. 👩‍💻 Follow the instructions for the [tenforce/virtuoso](https://hub.docker.com/r/tenforce/virtuoso/) image (https://hub.docker.com/r/tenforce/virtuoso), to start the Virtuoso triplestore using the `docker run` command. You will only need to change the shared volume:\n\n\n* They defined `-v /my/path/to/the/virtuoso/db:/data`. Change it to the `data/virtuoso` folder in your current directory, the path on the left of the `:` is for your computer, the path on the right is where the volume is shared in the container.\n\n* To provide the current directory as a shared volume with the docker container the variable to use is different for Windows:\n  \n    * For Linux 🐧 and Mac 🍎\n    \n      ```bash\n      -v $(pwd)/data/virtuoso:/data\n      ```\n    \n    * For Windows 🏢 (remove all the newlines with their extra `\\` to have one line):\n    \n      ```powershell\n      -v ${PWD}/data/virtuoso:/data\n      ```\n\n👨‍💻 Access the Virtuoso triplestore on http://localhost:8890 (admin login: `dba` / `dba`)\n\n\u003e You can also check how Virtuoso is installed in the image [Dockerfile](https://github.com/tenforce/docker-virtuoso/blob/master/Dockerfile)\n\n---\n\n## Task 2: Start the database container with a docker-compose file 📋\n\nOpen the `docker-compose.yml` file provided in the workshop folder with your favourite IDE (we recommend VisualStudio Code if you don't know which one to use)\n\nFollow [tenforce/virtuoso](https://hub.docker.com/r/tenforce/virtuoso/) instructions to define a `docker-compose.yml` file to run Virtuoso, and make some changes:\n\n* Define a fixed container name: `container_name: virtuoso` \n* Use the `latest` tag of the image: `tenforce/virtuoso:latest`\n* Set the `DBA_PASSWORD` environment variable to `dba`\n* Change the `DEFAULT_GRAPH` to https://w3id.org/um/ids/graph\n* Keep the `volumes` as described in tenforce/virtuoso, the triplestore `/data` files will be shared on your computer in `./data/virtuoso`\n  * N.B.: `docker-compose` uses `./` to define a volume path from the directory where the YAML file is stored\n\n\u003e ⚠️ Be careful with the indentation, it is meaningful in YAML files\n\n👩‍💻 Start the containers defined in the `docker-compose.yml` file from your terminal:\n\n```shell\ndocker-compose up\n```\n\nYou can check running Docker containers on your laptop via the Docker Desktop U.I. or running this command in the terminal:\n\n```shell\ndocker ps\n```\n\n\u003e Try to access the Virtuoso triplestore running on http://localhost:8890\n\nStop the docker-compose running in your terminal by hitting the keys `ctrl + c`\n\n👨‍💻 Run the containers detached from your terminal (in the background):\n\n```shell\ndocker-compose up -d\n```\n\n👩‍💻 Check the logs of the running containers:\n\n```shell\ndocker-compose logs\n```\n\n👨‍💻 Stop the running containers:\n\n```shell\ndocker-compose down\n```\n\n---\n\n## Task 3: Add JupyterLab to the docker-compose 🔭\n\nWe want to run a JupyterLab to query our Virtuoso triplestore. \n\n* We could try to install locally the [IJava kernel](https://github.com/SpencerPark/IJava) and the [SPARQL kernel](https://github.com/paulovn/sparql-kernel), but it will take more time and will be prone to installation errors and conflicts ❌ (We already tried with our students in the bachelor program!)\n* The easiest would be to start a JupyterLab Docker container with the 2 kernels pre-installed ✔️\n\n🍀 Luckily there is already a Docker image with all those kernels installed! \n\nThe image is hosted in the [GitHub Container Registry](https://github.com/users/vemonet/packages/container/package/jupyterlab), and is defined in this GitHub repository: https://github.com/vemonet/Jupyterlab\n\n\u003e If you are already comfortable with Docker, feel free to [try the advanced workshop using the official Jupyter Docker image](https://github.com/MaastrichtU-IDS/get-started-with-docker/tree/main/advanced). This workshop adds a new dimension to Docker deployment with managing files, permissions and owners.\n\n1. 👩‍💻 Look into the JupyterLab Docker image documentation to find out how to deploy it with `docker-compose`\n\n2. You will need to change (be careful with the indentation, it is meaningful in YAML files):\n\n    * The mapping from the JupyterLab container port `8888` to your computer port `8080`. Use `8080:8888`\n    * The shared volume to `./data/jupyterlab:/notebooks`\n    \n    \u003e Notice that the path/port mappings between your local machine and the container are always defined on the same side of the `:`\n    \u003e\n    \u003e * On your **local machine: always on the left ⬅️**\n    \u003e * In the **container: always on the right ➡️**\n\n3. Start JupyterLab and Virtuoso:\n\n```shell\ndocker-compose up\n```\n\nAccess JupyterLab on http://localhost:8080 (or 8888 depending on what you defined) and Virtuoso on http://localhost:8890\n\n5. Query the Virtuoso database from the JupyterLab container\n   \n   * Create a new **SPARQL Notebook** in JupyterLab\n   \n   * Create a cell to run a SPARQL query on the Virtuoso triplestore SPARQL endpoint:\n   \n     ```SPARQL\n     %endpoint http://db:8890/sparql\n     SELECT * WHERE {\n         ?s ?p ?o .\n     } LIMIT 10\n     ```\n   \n   * Now **run the cell** to query the triplestore from the notebook 🚀\n\n\u003e By default `docker-compose` will create a network so that the services can access each other using their service identifier from the YAML as URL without the need to expose the ports. \n\u003e\n\u003e 💡 This allows you to quickly deploy a public application with a database in the background.\n\n---\n\n\n## Task 4: Customize the Docker image 📦\n\nWe will improve the `Dockerfile` of the JupyterLab container to build a custom image with additional packages installed.\n\n\u003e Checkout the [Dockerfile of the JupyterLab image](https://github.com/vemonet/Jupyterlab/blob/main/Dockerfile) to see how a complete image can be built.\n\nOpen the `Dockerfile` provided in the workshop folder to define your image.\n\nIt will start from the JupyterLab image we were previously using:\n\n```dockerfile\nFROM ghcr.io/vemonet/jupyterlab\n```\n\n👩‍💻 Install the python package `rdflib` with `pip install` in the `Dockerfile` (💡 bonus: you can also use the `requirements.txt` file to install the `rdflib` package in the container)\n\n👩‍💻 Change the `docker-compose.yml` to build the container from the local `Dockerfile`, instead of using an existing image:\n\n```yaml\nservices:\n  jupyterlab:\n    # image: ghcr.io/vemonet/jupyterlab\n    build: .\n```\n\n👨‍💻 Build and restart JupyterLab from the terminal:\n\n```shell\ndocker-compose up --build\n```\n\n\u003e You can also build the image using the `docker` command:\n\u003e\n\u003e ```shell\n\u003e docker build -t my-jupyterlab .\n\u003e ```\n\u003e\n\n👩‍💻 Access the JupyterLab, create a new **Python Notebook**, and try out `rdflib` with autocomplete and suggestions:\n\n1. Create and run a cell to import `rdflib`:\n\n   ```python\n   import rdflib\n   ```\n\n2. Create a graph using autocomplete\n\n   ```python\n   rdflib.\n   # Now hit the keys `ctrl + space` to show the suggestions\n   ```\n\n\u003e You can check the [Translator OpenPredict API](https://github.com/MaastrichtU-IDS/translator-openpredict) to see an example of a complete Python application with database backend running with Docker:\n\u003e\n\u003e * Check the [Python API `Dockerfile`](https://github.com/MaastrichtU-IDS/translator-openpredict/blob/master/Dockerfile)\n\u003e * Check the [`docker-compose.yml`](https://github.com/MaastrichtU-IDS/translator-openpredict/blob/master/docker-compose.yml) to deploy the API with a Virtuoso database\n\n---\n\n## Task 5: Log in to Container Registries 🔑\n\nIt is recommended to login to existing Container Registries if you have a user on their platform (e.g. DockerHub, GitHub), it will enable higher download limitations and rates! 🏆\n\n### Login to DockerHub\n\n1. Get a [DockerHub](https://hub.docker.com/) account at https://hub.docker.com (you most probably already have one if you installed Docker Desktop)\n\n2. 👩‍💻 Run in your terminal:\n\n```bash\ndocker login\n```\n\n3. Provide your DockerHub username and password.\n\n### Login to GitHub Container Registry\n\nUse your existing [GitHub](https://github.com) account if you have one:\n\n1. Create a **Personal Access Token** for GitHub packages at **https://github.com/settings/tokens/new**\n1. Provide a meaningful description for the token, and enable the following scopes when creating the token:\n    * `write:packages`: publish container images to GitHub Container Registry\n    * `delete:packages`: delete specified versions of private or public container images from GitHub Container Registry\n1. You might want to store this token in a safe place, as you will not be able to retrieve it later on github.com (you can still delete it, and create a new token easily if you lose your token)\n1. 👨‍💻 Log in to the GitHub Container Registry in your terminal (change `USERNAME` and `ACCESS_TOKEN` to yours):\n\n```bash\necho \"ACCESS_TOKEN\" | docker login ghcr.io -u USERNAME --password-stdin\n```\n\n\u003e See the [official GitHub documentation](https://docs.github.com/en/free-pro-team@latest/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages).\n\n---\n\n## Bonus: Publish your image 📢\n\nOnce you built a Docker image, and you logged in to a Container Registry, you might want to publish the image to pull and re-use it easily later.\n\n### Publish to GitHub Container Registry\n\nThe [GitHub Container Registry](https://docs.github.com/en/free-pro-team@latest/packages/getting-started-with-github-container-registry) is still in beta but will be free for public images when fully released. It enables you to store your Docker images at the same place you keep your code! 📦\n\nPublish to your user Container Registry on GitHub:\n\n```bash\ndocker build -t ghcr.io/github-username/jupyterlab:latest .\ndocker push ghcr.io/github-username/jupyterlab:latest\n```\n\nOr to the [MaastrichtU-IDS Container Registry on GitHub](https://github.com/orgs/MaastrichtU-IDS/packages):\n\n```bash\ndocker build -t ghcr.io/vemonet/jupyterlab:latest .\ndocker push ghcr.io/vemonet/jupyterlab:latest\n```\n\n\u003e If the image does not exist, GitHub Container Registry will create automatically and set it as **Private** by default. You can easily change it to **Public** in your image settings on GitHub.\n\n### Publish to DockerHub\n\n[DockerHub](https://hub.docker.com/) is still the most popular and mature Container Registry, and the new rates should not impact a regular user.\n\nFirst, create the repository on [DockerHub](https://hub.docker.com/) (attached to your user or an [organization](https://hub.docker.com/orgs/umids/repositories)), then build and push the image:\n\n```bash\ndocker build -t dockerhub-username/jupyterlab:latest .\ndocker push dockerhub-username/jupyterlab:latest\n```\n\n\u003e You can also change the name (aka. tag) of an existing image:\n\u003e\n\u003e ```bash\n\u003e docker build -t my-jupyterlab .\n\u003e docker tag my-jupyterlab ghcr.io/github-username/jupyterlab:latest\n\u003e ```\n\n### Use automated workflows\n\nYou can automate the building and publication of Docker images using GitHub Actions workflows 🔄\n\n👀 Check the [`.github/workflows/publish-docker.yml` file](https://github.com/MaastrichtU-IDS/get-started-with-docker/blob/main/.github/workflows/publish-docker.yml) to see an example of a workflow to publish an image to the GitHub Container Registry.\n\n👩‍💻 You only need to change the `IMAGE_NAME`, and use it in your GitHub repository to publish a Docker image for your application automatically! It will build from a `Dockerfile` at the root of the repository.\n\nThe workflow can be easily configured to:\n\n* publish a new image to the `latest` tag at each push to the main branch\n* publish an image to a new tag if a release is pushed on GitHub (using the git tag)\n  * e.g. `v0.0.1` published as image `0.0.1`\n\n\u003e If you publish your image on DockerHub, you can use [automated build on DockerHub](https://docs.docker.com/docker-hub/builds/).\n\n\u003e GitHub Actions is still currently evolving quickly, feel free to check if they recommend a new way to build and publish containers 🚀\n\n---\n\n## Check the solution ✔️\n\nGo in the [`solution` folder](https://github.com/MaastrichtU-IDS/get-started-with-docker/tree/main/solution) to check the solution:\n\n* `README.md` for the general solution guidelines, and to run Virtuoso with the `docker run` command\n* `Dockerfile` with root user and additional packages installed for a custom JupyterLab image\n* `docker-compose.yml` to build and run a custom JupyterLab container and a Virtuoso database\n* `docker-compose.advanced.yml` to run the official JupyterLab container and a Virtuoso database\n\n\u003e See also, the previous docker-workshop provided by IDS: https://github.com/MaastrichtU-IDS/docker-workshop\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaastrichtu-ids%2Fget-started-with-docker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaastrichtu-ids%2Fget-started-with-docker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaastrichtu-ids%2Fget-started-with-docker/lists"}