mirror of https://github.com/docker/docs.git
Merge pull request #20563 from dvdksn/learning-paths
site: add learning paths
This commit is contained in:
commit
b7f0232bc6
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
After Width: | Height: | Size: 127 KiB |
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
title: Learning paths
|
||||
description: |
|
||||
Docker Learning Paths offer structured guides to help you master Docker.
|
||||
keywords: docker, learning, paths, tutorials, resources
|
||||
---
|
||||
|
||||
<p class="w-2/3">
|
||||
Docker Learning Paths offer structured guides to help you master Docker tools
|
||||
and services. Each path includes tutorials and resources on topics like Docker
|
||||
Scout and Docker Build Cloud. Start learning at your own pace and enhance your
|
||||
Docker skills.
|
||||
</p>
|
|
@ -0,0 +1,158 @@
|
|||
---
|
||||
title: "Docker Build Cloud: Reclaim your time with fast, multi-architecture builds"
|
||||
description: |
|
||||
Learn how to build and deploy Docker images to the cloud with Docker Build Cloud.
|
||||
summary: |
|
||||
Create applications up to 39x faster using cloud-based resources, shared team cache, and native multi-architecture support.
|
||||
params:
|
||||
image: images/learning-paths/build-cloud.png
|
||||
skill: Beginner
|
||||
time: 10 minutes
|
||||
prereq: None
|
||||
---
|
||||
|
||||
{{< columns >}}
|
||||
|
||||
<!-- vale Vale.Spelling = NO -->
|
||||
|
||||
98% of developers spend up to an hour every day waiting for builds to finish
|
||||
([Incredibuild: 2022 Big Dev Build Times](https://www.incredibuild.com/survey-report-2022)).
|
||||
Heavy, complex builds can become a major roadblock for development teams,
|
||||
slowing down both local development and CI/CD pipelines.
|
||||
|
||||
<!-- vale Vale.Spelling = YES -->
|
||||
|
||||
Docker Build Cloud speeds up image build times to improve developer
|
||||
productivity, reduce frustrations, and help you shorten the release cycle.
|
||||
|
||||
## Who’s this for?
|
||||
|
||||
- Anyone who wants to tackle common causes of slow image builds: limited local
|
||||
resources, slow emulation, and lack of build collaboration across a team.
|
||||
- Developers working on older machines who want to build faster.
|
||||
- Development teams working on the same repository who want to cut wait times
|
||||
with a shared cache.
|
||||
- Developers performing multi-architecture builds who don’t want to spend hours
|
||||
configuring and rebuilding for emulators.
|
||||
|
||||
<!-- break -->
|
||||
|
||||
## What you’ll learn
|
||||
|
||||
- Building container images faster locally and in CI
|
||||
- Accelerating builds for multi-platform images
|
||||
- Reusing pre-built images to expedite workflows
|
||||
|
||||
## Tools integration
|
||||
|
||||
Works well with Docker Compose, GitHub Actions, and other CI solutions
|
||||
|
||||
{{< /columns >}}
|
||||
|
||||
## Modules
|
||||
|
||||
{{< accordion large=true title=`Why Docker Build Cloud?` icon=`play_circle` >}}
|
||||
|
||||
Docker Build Cloud is a service that lets you build container images faster,
|
||||
both locally and in CI. Builds run on cloud infrastructure optimally
|
||||
dimensioned for your workloads, with no configuration required. The service
|
||||
uses a remote build cache, ensuring fast builds anywhere and for all team
|
||||
members.
|
||||
|
||||
- Docker Build Cloud provides several benefits over local builds:
|
||||
- Improved build speed
|
||||
- Shared build cache
|
||||
- Native multi-platform builds
|
||||
|
||||
There’s no need to worry about managing builders or infrastructure — simply
|
||||
connect to your builders and start building. Each cloud builder provisioned to
|
||||
an organization is completely isolated to a single Amazon EC2 instance, with a
|
||||
dedicated EBS volume for build cache and encryption in transit. That means
|
||||
there are no shared processes or data between cloud builders.
|
||||
|
||||
{{< youtube-embed "8AqKhEO2PQA" >}}
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Demo: using Docker Build Cloud in CI` icon=`play_circle` >}}
|
||||
|
||||
Speed up your build pipelines — delegate the build execution to Docker Build Cloud in CI.
|
||||
|
||||
{{< youtube-embed "wvLdInoVBGg" >}}
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Common challenges and questions` icon=`quiz` >}}
|
||||
|
||||
### Is Docker Build Cloud a standalone product or a part of Docker Desktop?
|
||||
|
||||
Docker Build Cloud is a service that can be used both with Docker Desktop and
|
||||
standalone. It lets you build your container images faster, both locally and in
|
||||
CI, with builds running on cloud infrastructure. The service uses a remote
|
||||
build cache, ensuring fast builds anywhere and for all team members.
|
||||
|
||||
When used with Docker Desktop, the [Builds view](/desktop/use-desktop/builds/)
|
||||
works with Docker Build Cloud out-of-the-box. It shows information about your
|
||||
builds and those initiated by your team members using the same builder,
|
||||
enabling collaborative troubleshooting.
|
||||
|
||||
To use Docker Build Cloud without Docker Desktop, you must
|
||||
[download and install](/build-cloud/setup/#use-docker-build-cloud-without-docker-desktop)
|
||||
a version of Buildx with support for Docker Build Cloud (the `cloud` driver).
|
||||
If you plan on building with Docker Build Cloud using the `docker compose
|
||||
build` command, you also need a version of Docker Compose that supports Docker
|
||||
Build Cloud.
|
||||
|
||||
### How does Docker Build Cloud work with Docker Compose?
|
||||
|
||||
Docker Compose works out of the box with Docker Build Cloud. Install the Docker
|
||||
Build Cloud-compatible client (buildx) and it works with both commands.
|
||||
|
||||
### How many minutes are included in Docker Build Cloud Team plans?
|
||||
|
||||
You receive 200 minutes per month per purchased seat. If you are also a Docker
|
||||
subscriber (Personal, Pro, Team, Business), you will also receive your included
|
||||
build minutes from that plan.
|
||||
|
||||
For example, if a Docker Team customer purchases 5 Build Cloud Team seats, they
|
||||
will have 400 minutes from their Docker Team plan plus 1000 minutes (200 min/mo
|
||||
* 5 seats) for a total of 1400 minutes per month.
|
||||
|
||||
### I’m a Docker personal user. Can I try Docker Build Cloud?
|
||||
|
||||
Docker subscribers (Pro, Team, Business) receive a set number of minutes each
|
||||
month, shared across the account, to use Build Cloud.
|
||||
|
||||
If you do not have a Docker subscription, you may sign up for a free Personal
|
||||
account and get 50 minutes per month. Personal accounts are limited to a single
|
||||
user.
|
||||
|
||||
For teams to receive the shared cache benefit, they must either be on a Docker
|
||||
Team, Docker Business, or paid Build Cloud Team plan. You may buy a month of
|
||||
Build Cloud Team for the number of seats testing.
|
||||
|
||||
### Does Docker Build Cloud support CI platforms? Does it work with GitHub Actions?
|
||||
|
||||
Yes, Docker Build Cloud can be used with various CI platforms including GitHub
|
||||
Actions, CircleCI, Jenkins, and others. It can speed up your build pipelines,
|
||||
which means less time spent waiting and context switching.
|
||||
|
||||
Docker Build Cloud can be used with GitHub Actions to automate your build,
|
||||
test, and deployment pipeline. Docker provides a set of official GitHub Actions
|
||||
that you can use in your workflows.
|
||||
|
||||
Using GitHub Actions with Docker Build Cloud is straightforward. With a
|
||||
one-line change in your GitHub Actions configuration, everything else stays the
|
||||
same. You don't need to create new pipelines. Learn more in the [CI
|
||||
documentation](/build-cloud/ci/) for Docker Build Cloud.
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Resources` icon=`link` >}}
|
||||
|
||||
- [Product page](https://www.docker.com/products/build-cloud/)
|
||||
- [Docker Build Cloud overview](/build-cloud/)
|
||||
- [Subscriptions and features](/subscription/build-cloud/build-details/)
|
||||
- [Using Docker Build Cloud](/build-cloud/usage/)
|
||||
|
||||
{{< /accordion >}}
|
|
@ -0,0 +1,156 @@
|
|||
---
|
||||
title: Defining and Running Multi-Container Applications with Docker Compose
|
||||
summary: Simplify the process of defining, configuring, and running multi-container Docker applications to enable efficient development, testing, and deployment.
|
||||
description: Learn how to use Docker Compose to define and run multi-container Docker applications.
|
||||
params:
|
||||
image: images/learning-paths/compose.png
|
||||
skill: Beginner
|
||||
time: 5 minutes
|
||||
prereq: None
|
||||
---
|
||||
|
||||
{{< columns >}}
|
||||
|
||||
Developers face challenges with multi-container Docker applications, including
|
||||
complex configuration, dependency management, and maintaining consistent
|
||||
environments. Networking, resource allocation, data persistence, logging, and
|
||||
monitoring add to the difficulty. Security concerns and troubleshooting issues
|
||||
further complicate the process, requiring effective tools and practices for
|
||||
efficient management.
|
||||
|
||||
Docker Compose solves the problem of managing multi-container Docker
|
||||
applications by providing a simple way to define, configure, and run all the
|
||||
containers needed for an application using a single YAML file. This approach
|
||||
helps developers to easily set up, share, and maintain consistent development,
|
||||
testing, and production environments, ensuring that complex applications can be
|
||||
deployed with all their dependencies and services properly configured and
|
||||
orchestrated.
|
||||
|
||||
<!-- break -->
|
||||
|
||||
## Who’s this for?
|
||||
|
||||
- Developers and DevOps engineers who need to define, manage, and orchestrate
|
||||
multi-container Docker applications efficiently across multiple environments.
|
||||
- Development teams that want to increase productivity by streamlining
|
||||
development workflows and reducing setup time.
|
||||
|
||||
## Tools integration
|
||||
|
||||
Works well with Docker CLI, CI/CD tools, and container orchestration tools.
|
||||
|
||||
{{< /columns >}}
|
||||
|
||||
## Modules
|
||||
|
||||
{{< accordion large=true title=`Why Docker Compose?` icon=`play_circle` >}}
|
||||
|
||||
Docker Compose is an essential tool for defining and running multi-container
|
||||
Docker applications. Docker Compose simplifies the Docker experience, making it
|
||||
easier for developers to create, manage, and deploy applications by using YAML
|
||||
files to configure application services.
|
||||
|
||||
Docker Compose provides several benefits:
|
||||
|
||||
- Lets you define multi-container applications in a single YAML file.
|
||||
- Ensures consistent environments across development, testing, and production.
|
||||
- Manages the startup and linking of multiple containers effortlessly.
|
||||
- Streamlines development workflows and reduces setup time.
|
||||
- Ensures that each service runs in its own container, avoiding conflicts.
|
||||
|
||||
{{< youtube-embed 2EqarOM2V4U >}}
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Demo: Set up and use Docker Compose` icon=`play_circle` >}}
|
||||
|
||||
{{< youtube-embed P5RBKmOLPH4 >}}
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Common challenges and questions` icon=`quiz` >}}
|
||||
|
||||
<!-- vale Docker.HeadingLength = NO -->
|
||||
|
||||
### Do I need to maintain a separate Compose file for my development, testing, and staging environments?
|
||||
|
||||
You don't necessarily need to maintain entirely separate Compose files for your
|
||||
development, testing, and staging environments. You can define all your
|
||||
services in a single Compose file (`compose.yml`). You can use profiles to
|
||||
group service configurations specific to each environment (`dev`, `test`,
|
||||
`staging`).
|
||||
|
||||
When you need to spin up an environment, you can activate the corresponding
|
||||
profiles. For example, to set up the development environment:
|
||||
|
||||
```console
|
||||
$ docker compose --profile dev up
|
||||
```
|
||||
|
||||
This command starts only the services associated with the `dev` profile,
|
||||
leaving the rest inactive.
|
||||
|
||||
For more information on using profiles, see [Using profiles with
|
||||
Compose](/compose/profiles/).
|
||||
|
||||
### How can I enforce the database service to start up before the frontend service?
|
||||
|
||||
Docker Compose ensures services start in a specific order by using the
|
||||
`depends_on` property. This tells Compose to start the database service before
|
||||
even attempting to launch the frontend service. This is crucial since
|
||||
applications often rely on databases being ready for connections.
|
||||
|
||||
However, `depends_on` only guarantees the order, not that the database is fully
|
||||
initialized. For a more robust approach, especially if your application relies
|
||||
on a prepared database (e.g., after migrations), consider [health
|
||||
checks](/reference/compose-file/services.md#healthcheck). Here, you can
|
||||
configure the frontend to wait until the database passes its health check
|
||||
before starting. This ensures the database is not only up but also ready to
|
||||
handle requests.
|
||||
|
||||
For more information on setting the startup order of your services, see
|
||||
[Control startup and shutdown order in Compose](/compose/startup-order/).
|
||||
|
||||
### Can I use Compose to build a Docker image?
|
||||
|
||||
Yes, you can use Docker Compose to build Docker images. Docker Compose is a
|
||||
tool for defining and running multi-container applications. Even if your
|
||||
application isn't a multi-container application, Docker Compose can make it
|
||||
easier to run by defining all the `docker run` options in a file.
|
||||
|
||||
To use Compose, you need a `compose.yml` file. In this file, you can specify
|
||||
the build context and Dockerfile for each service. When you run the command
|
||||
`docker compose up --build`, Docker Compose will build the images for each
|
||||
service and then start the containers.
|
||||
|
||||
For more information on building Docker images using Compose, see the [Compose
|
||||
Build Specification](/compose/compose-file/build/).
|
||||
|
||||
### What is the difference between Docker Compose and Dockerfile?
|
||||
|
||||
A Dockerfile provides instructions to build a container image while a Compose
|
||||
file defines your running containers. Quite often, a Compose file references a
|
||||
Dockerfile to build an image to use for a particular service.
|
||||
|
||||
### What is the difference between the `docker compose up` and `docker compose run` commands?
|
||||
|
||||
The `docker compose up` command creates and starts all your services. It's
|
||||
perfect for launching your development environment or running the entire
|
||||
application. The `docker compose run` command focuses on individual services.
|
||||
It starts a specified service along with its dependencies, allowing you to run
|
||||
tests or perform one-off tasks within that container.
|
||||
|
||||
<!-- vale Docker.HeadingLength = YES -->
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Resources` icon=`link` >}}
|
||||
|
||||
- [Overview of Docker Compose CLI](/compose/reference/)
|
||||
- [Overview of Docker Compose](/compose/)
|
||||
- [How Compose works](/compose/compose-application-model/)
|
||||
- [Using profiles with Compose](/compose/profiles/)
|
||||
- [Control startup and shutdown order with Compose](/compose/startup-order/)
|
||||
- [Compose Build Specification](/compose/compose-file/build/)
|
||||
|
||||
{{< /accordion >}}
|
|
@ -0,0 +1,177 @@
|
|||
---
|
||||
title: Securing your software supply chain with Docker Scout
|
||||
summary: |
|
||||
Enhance container security by automating vulnerability detection and
|
||||
remediation, ensuring compliance, and protecting your development workflow.
|
||||
description: |
|
||||
Learn how to use Docker Scout to enhance container security by automating
|
||||
vulnerability detection and remediation, ensuring compliance, and protecting
|
||||
your development workflow.
|
||||
params:
|
||||
image: images/learning-paths/scout.png
|
||||
skill: Beginner
|
||||
time: 10 minutes
|
||||
prereq: None
|
||||
---
|
||||
|
||||
{{< columns >}}
|
||||
|
||||
When container images are insecure, significant risks can arise. Around 60% of
|
||||
organizations have reported experiencing at least one security breach or
|
||||
vulnerability incident within a year, resulting in operational
|
||||
disruption.[^CSA] These incidents often result in considerable downtime, with
|
||||
44% of affected companies experiencing over an hour of downtime per event. The
|
||||
financial impact is substantial, with the average data breach cost reaching
|
||||
$4.45 million.[^IBM] This highlights the critical importance of maintaining
|
||||
robust container security measures.
|
||||
|
||||
Docker Scout enhances container security by providing automated vulnerability
|
||||
detection and remediation, addressing insecure container images, and ensuring
|
||||
compliance with security standards.
|
||||
|
||||
[^CSA]: https://cloudsecurityalliance.org/blog/2023/09/21/2023-global-cloud-threat-report-cloud-attacks-are-lightning-fast
|
||||
[^IBM]: https://www.ibm.com/reports/data-breach
|
||||
|
||||
<!-- break -->
|
||||
|
||||
## What you'll learn
|
||||
|
||||
- Define secure software supply chain (SSSC)
|
||||
- Review SBOMs and how to use them
|
||||
- Detect and monitor vulnerabilities
|
||||
|
||||
## Tools integration
|
||||
|
||||
Works well with Docker Desktop, GitHub Actions, Jenkins, Kubernetes, and
|
||||
other CI solutions.
|
||||
|
||||
{{< /columns >}}
|
||||
|
||||
## Who’s this for?
|
||||
|
||||
DevOps engineers who need to integrate automated security checks into CI/CD
|
||||
pipelines to enhance the security and efficiency of their workflows. Developers
|
||||
who want to use Docker Scout to identify and remediate vulnerabilities early in
|
||||
the development process, ensuring the production of secure container images.
|
||||
Security professionals who must enforce security compliance, conduct
|
||||
vulnerability assessments, and ensure the overall security of containerized
|
||||
applications.
|
||||
|
||||
## Modules
|
||||
|
||||
{{< accordion large=true title=`Why Docker Scout?` icon=`play_circle` >}}
|
||||
|
||||
Organizations face significant challenges from data breaches,
|
||||
including financial losses, operational disruptions, and long-term damage to
|
||||
brand reputation and customer trust. Docker Scout addresses critical problems
|
||||
such as identifying insecure container images, preventing security breaches,
|
||||
and reducing the risk of operational downtime due to vulnerabilities.
|
||||
|
||||
Docker Scout provides several benefits:
|
||||
|
||||
- Secure and trusted content
|
||||
- A system of record for your SDLC
|
||||
- Continuous security posture improvement
|
||||
|
||||
Docker Scout offers automated vulnerability detection and remediation, helping
|
||||
organizations identify and fix security issues in container images early in the
|
||||
development process. It also integrates with popular development tools like
|
||||
Docker Desktop and GitHub Actions, providing seamless security management and
|
||||
compliance checks within existing workflows.
|
||||
|
||||
{{< youtube-embed "-omsQ7Uqyc4" >}}
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Docker Scout Demo` icon=`play_circle` >}}
|
||||
|
||||
Organizations face significant challenges from data breaches,
|
||||
including financial losses, operational disruptions, and long-term damage to
|
||||
brand reputation and customer trust. Docker Scout addresses critical problems
|
||||
such as identifying insecure container images, preventing security breaches,
|
||||
and reducing the risk of operational downtime due to vulnerabilities.
|
||||
|
||||
Docker Scout provides several benefits:
|
||||
|
||||
- Secure and trusted content
|
||||
- A system of record for your SDLC
|
||||
- Continuous security posture improvement
|
||||
|
||||
Docker Scout offers automated vulnerability detection and remediation, helping
|
||||
organizations identify and fix security issues in container images early in the
|
||||
development process. It also integrates with popular development tools like
|
||||
Docker Desktop and GitHub Actions, providing seamless security management and
|
||||
compliance checks within existing workflows.
|
||||
|
||||
{{< youtube-embed "TkLwJ0p46W8" >}}
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Common challenges and questions` icon=`quiz` >}}
|
||||
|
||||
<!-- vale Docker.HeadingLength = NO -->
|
||||
|
||||
### How is Docker Scout different from other security tools?
|
||||
|
||||
Docker Scout takes a broader approach to container security compared to
|
||||
third-party security tools. Third-party security tools, if they offer
|
||||
remediation guidance at all, miss the mark on their limited scope of
|
||||
application security posture within the software supply chain, and often
|
||||
limited guidance when it comes to suggested fixes. Such tools have either
|
||||
limitations on runtime monitoring or no runtime protection at all. When they do
|
||||
offer runtime monitoring, it’s limited in its adherence to key policies.
|
||||
Third-party security tools offer a limited scope of policy evaluation for
|
||||
Docker-specific builds. By focusing on the entire software supply chain,
|
||||
providing actionable guidance, and offering comprehensive runtime protection
|
||||
with strong policy enforcement, Docker Scout goes beyond just identifying
|
||||
vulnerabilities in your containers. It helps you build secure applications from
|
||||
the ground up.
|
||||
|
||||
### Can I use Docker Scout with external registries other than Docker Hub?
|
||||
|
||||
You can use Scout with registries other than Docker Hub. Integrating Docker Scout
|
||||
with third-party container registries enables Docker Scout to run image
|
||||
analysis on those repositories so that you can get insights into the
|
||||
composition of those images even if they aren't hosted on Docker Hub.
|
||||
|
||||
The following container registry integrations are available:
|
||||
|
||||
- Artifactory
|
||||
- Amazon Elastic Container Registry
|
||||
- Azure Container Registry
|
||||
|
||||
Learn more about configuring Scout with your registries in [Integrating Docker Scout with third-party registries](/scout/integrations/#container-registries).
|
||||
|
||||
### Does Docker Scout CLI come by default with Docker Desktop?
|
||||
|
||||
Yes, the Docker Scout CLI plugin comes pre-installed with Docker Desktop.
|
||||
|
||||
### Is it possible to run `docker scout` commands on a Linux system without Docker Desktop?
|
||||
|
||||
If you run Docker Engine without Docker Desktop, Docker Scout doesn't come
|
||||
pre-installed, but you can [install it as a standalone binary](/scout/install/).
|
||||
|
||||
### How is Docker Scout using an SBOM?
|
||||
|
||||
An SBOM, or software bill of materials, is a list of ingredients that make up
|
||||
software components. [Docker Scout uses SBOMs](/scout/concepts/sbom/) to
|
||||
determine the components that are used in a Docker image. When you analyze an
|
||||
image, Docker Scout will either use the SBOM that is attached to the image (as
|
||||
an attestation), or generate an SBOM on the fly by analyzing the contents of
|
||||
the image.
|
||||
|
||||
The SBOM is cross-referenced with the advisory database to determine if any of
|
||||
the components in the image have known vulnerabilities.
|
||||
|
||||
{{< /accordion >}}
|
||||
|
||||
{{< accordion large=true title=`Resources` icon=`link` >}}
|
||||
|
||||
- [Docker Scout overview](/scout/)
|
||||
- [Docker Scout quickstart](/scout/quickstart/)
|
||||
- [Install Docker Scout](/scout/install/)
|
||||
- [Software Bill of Materials](/scout/concepts/sbom/)
|
||||
|
||||
<!-- vale Docker.HeadingLength = YES -->
|
||||
|
||||
{{< /accordion >}}
|
|
@ -2446,3 +2446,13 @@ Manuals:
|
|||
title: Get support
|
||||
- path: /release-lifecycle/
|
||||
title: Product release lifecycle
|
||||
|
||||
Learning paths:
|
||||
- title: Overview
|
||||
path: /learning-paths/
|
||||
- title: Docker Build Cloud
|
||||
path: /learning-paths/docker-build-cloud/
|
||||
- title: Docker Scout
|
||||
path: /learning-paths/docker-scout/
|
||||
- title: Docker Compose
|
||||
path: /learning-paths/docker-compose/
|
||||
|
|
|
@ -132,6 +132,9 @@ menus:
|
|||
- name: Reference
|
||||
url: /reference/
|
||||
weight: 4
|
||||
- name: Learning paths
|
||||
url: /learning-paths/
|
||||
weight: 5
|
||||
|
||||
footer:
|
||||
- url: https://www.docker.com/products
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"--mount",
|
||||
"--tmpfs",
|
||||
"-mb-3",
|
||||
"-mt-1",
|
||||
"-mt-4",
|
||||
"-top-16",
|
||||
"-v",
|
||||
|
@ -287,7 +288,9 @@
|
|||
"h-16",
|
||||
"h-2",
|
||||
"h-32",
|
||||
"h-48",
|
||||
"h-8",
|
||||
"h-96",
|
||||
"h-auto",
|
||||
"h-full",
|
||||
"h-max",
|
||||
|
@ -376,10 +379,12 @@
|
|||
"my-0",
|
||||
"my-2",
|
||||
"my-4",
|
||||
"my-6",
|
||||
"my-8",
|
||||
"no-underline",
|
||||
"no-wrap",
|
||||
"not-prose",
|
||||
"object-cover",
|
||||
"openSUSE-and-SLES",
|
||||
"origin-bottom-right",
|
||||
"outline",
|
||||
|
@ -443,6 +448,8 @@
|
|||
"shadow",
|
||||
"sidebar-hover",
|
||||
"sm:flex-row",
|
||||
"sm:grid-cols-2",
|
||||
"sm:items-center",
|
||||
"space-x-2",
|
||||
"space-y-4",
|
||||
"sticky",
|
||||
|
@ -487,6 +494,7 @@
|
|||
"underline-offset-2",
|
||||
"underline-offset-8",
|
||||
"w-2",
|
||||
"w-2/3",
|
||||
"w-8",
|
||||
"w-[1200px]",
|
||||
"w-[32px]",
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{{- else if (strings.HasPrefix $url "/") -}}
|
||||
{{ if (strings.HasSuffix (urls.Parse $url).Path ".md") }}
|
||||
{{/* abs path to markdown file, use ref */}}
|
||||
{{ $url = (ref .Page $url) }}
|
||||
{{ $url = (ref page $url) }}
|
||||
{{ end }}
|
||||
<a class="link" href="{{ $url }}">{{ .Text | safeHTML }}</a>
|
||||
{{- else -}}
|
||||
|
@ -21,12 +21,12 @@
|
|||
{{- if (strings.FindRE `([^_]|^)index.md` $url 1) -}}
|
||||
<a
|
||||
class="link"
|
||||
href="{{ ref .Page (strings.Replace $url "index.md" "_index.md") }}"
|
||||
href="{{ ref page (strings.Replace $url "index.md" "_index.md") }}"
|
||||
>{{ .Text | safeHTML }}</a
|
||||
>
|
||||
{{- else -}}
|
||||
{{/* relative link, use ref */}}
|
||||
<a class="link" href="{{ ref .Page $url }}"
|
||||
<a class="link" href="{{ ref page $url }}"
|
||||
>{{ .Text | safeHTML }}</a
|
||||
>
|
||||
{{- end -}}
|
||||
|
|
|
@ -44,58 +44,9 @@
|
|||
</div>
|
||||
</main>
|
||||
<footer>{{ partialCached "footer.html" . }}</footer>
|
||||
{{ with (.Store.Get "youtube") }}
|
||||
<script>
|
||||
(function() {
|
||||
var tag = document.createElement('script');
|
||||
tag.id = "youtube-iframe-api";
|
||||
tag.src = "https://www.youtube.com/iframe_api";
|
||||
var firstScriptTag = document.getElementsByTagName('script')[0];
|
||||
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
||||
|
||||
window.onYouTubeIframeAPIReady = function() {
|
||||
var youtubeDivs = document.querySelectorAll(".youtube-video");
|
||||
for (var i = 0; i < youtubeDivs.length; i++) {
|
||||
createPlayer(youtubeDivs[i].id, youtubeDivs[i].dataset.videoId);
|
||||
}
|
||||
}
|
||||
|
||||
function createPlayer(domElementId, videoId) {
|
||||
new YT.Player(domElementId, {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
videoId: videoId,
|
||||
playerVars: {
|
||||
'rel': 0,
|
||||
'iv_load_policy': 3,
|
||||
'enablejsapi': 1,
|
||||
'origin': window.location.origin
|
||||
},
|
||||
events: {
|
||||
'onStateChange': function (event) {
|
||||
onPlayerStateChange(event, videoId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onPlayerStateChange(event, videoId) {
|
||||
if (window.heap === undefined) return;
|
||||
|
||||
var properties = {
|
||||
video_id: videoId,
|
||||
page_path: window.location.pathname,
|
||||
page_title: document.title,
|
||||
};
|
||||
|
||||
if (event.data == YT.PlayerState.PLAYING) {
|
||||
heap.track("Video Play", properties);
|
||||
} else if (event.data == YT.PlayerState.PAUSED) {
|
||||
heap.track("Video Paused", properties);
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
{{/* Load the YouTube player if the page embeds a YouTube video */}}
|
||||
{{ with .Store.Get "youtube" }}
|
||||
{{- partial "youtube-script.html" . }}
|
||||
{{ end }}
|
||||
</body>
|
||||
|
||||
|
|
|
@ -7,43 +7,14 @@
|
|||
<article class="prose max-w-none dark:prose-invert">
|
||||
<h1 data-pagefind-weight="10" class="scroll-mt-36">{{ .Title }}</h1>
|
||||
<div class="text-lg">{{ .Summary }}</div>
|
||||
<div class="not-prose">
|
||||
<div class="flex flex-col sm:flex-row w-full justify-between gap-4 p-6 m-4 bg-gray-light-200 dark:bg-gray-dark-300">
|
||||
<div class="flex flex-col">
|
||||
<span><strong>Skill level</strong></span>
|
||||
<span>{{ .Params.skill }}</span>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span><strong>Time to complete</strong></span>
|
||||
<span>{{ .Params.time }}</span>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span><strong>Prerequisites</strong></span>
|
||||
<span>{{ .Params.prereq }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ partial "components/guide-summary.html" . }}
|
||||
{{ .Content }}
|
||||
{{ partial "heading.html" (dict "text" "Modules" "level" 2) }}
|
||||
{{ range $i, $e := .Pages }}
|
||||
{{ $open := compare.Conditional (eq $i 0) true false }}
|
||||
<div x-data="{ open: {{ $open }} }" class="border border-gray-light-200 dark:border-gray-dark-200 bg-white dark:bg-gray-dark-100 py-2">
|
||||
<button class="not-prose w-full py-2 px-4 flex justify-between" x-on:click="open = ! open">
|
||||
<span class="text-xl">{{ fmt.Printf "%d. %s" (add $i 1) .Title }}</span>
|
||||
<span :class="{ 'hidden' : !open }" class="icon-svg">{{ partialCached "icon" "expand_less" "expand_less" }}</span>
|
||||
<span :class="{ 'hidden' : open }" class="icon-svg">{{ partialCached "icon" "expand_more" "expand_more" }}</span>
|
||||
</button>
|
||||
<div x-show="open" x-collapse class="px-4">
|
||||
<div class="mb-4">
|
||||
<div class="mb-4">{{ $e.Summary }}</div>
|
||||
<div>
|
||||
<a href="{{ $e.Permalink }}"
|
||||
class="no-underline cursor-pointer py-2 px-4 rounded bg-blue-light-500 dark:bg-blue-dark-400 hover:bg-blue-light-400 dark:hover:bg-blue-dark-500 text-white"
|
||||
>Start</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ $o := compare.Conditional (eq $i 0) true false }}
|
||||
{{ $t := fmt.Printf "%d. %s" (add $i 1) $e.Title }}
|
||||
{{ $b := fmt.Printf "%s\n\n{{< button url=`%s` text=`%s` >}}" $e.Summary $e.Permalink "Start" }}
|
||||
{{ partial "components/accordion.html" (dict "large" true "open" $o "title" $t "body" $b) }}
|
||||
{{ end }}
|
||||
</article>
|
||||
{{ end }}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
{{ partial "head.html" . }}
|
||||
</head>
|
||||
|
||||
<body class="flex flex-col min-h-screen bg-background-light text-base dark:bg-background-dark dark:text-white">
|
||||
{{ partial "header.html" . }}
|
||||
<main class="flex justify-center">
|
||||
<div class="lg:w-[1200px] overflow-clip p-6 pt-0 w-lvw">
|
||||
{{ block "main" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</main>
|
||||
<footer class="mt-auto">{{ partialCached "footer.html" . }}</footer>
|
||||
{{/* Load the YouTube player if the page embeds a YouTube video */}}
|
||||
{{ with .Store.Get "youtube" }}
|
||||
{{- partial "youtube-script.html" . }}
|
||||
{{ end }}
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
{{ define "main" }}
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<article class="prose max-w-none dark:prose-invert">
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
<hr>
|
||||
{{ partial "post-links.html" .Pages }}
|
||||
</article>
|
||||
{{ end }}
|
|
@ -0,0 +1,14 @@
|
|||
{{ define "main" }}
|
||||
{{ partial "breadcrumbs.html" . }}
|
||||
<article class="prose max-w-none dark:prose-invert">
|
||||
{{- $img := resources.Get .Params.image }}
|
||||
<img src="{{ $img.Permalink }}" alt="{{ .Title }}" class="w-full rounded-lg object-cover h-96">
|
||||
<h1 class="scroll-mt-36">{{ .Title }}</h1>
|
||||
<div class="text-lg">{{ .Summary }}</div>
|
||||
{{ partial "components/guide-summary.html" . }}
|
||||
{{ .Content }}
|
||||
<hr>
|
||||
<div class="text-xl">More learning paths</div>
|
||||
{{ partial "post-links.html" (where .CurrentSection.Pages "Permalink" "ne" page.Permalink) }}
|
||||
</article>
|
||||
{{ end }}
|
|
@ -1,11 +1,17 @@
|
|||
<div x-data="{ open: false }" class="border border-gray-light-200 dark:border-gray-dark-200 bg-white dark:bg-gray-dark-100">
|
||||
<div
|
||||
id="{{ urls.Anchorize .title }}"
|
||||
x-data="{ open: {{ .open | default false }} }" class="border border-gray-light-200 dark:border-gray-dark-200 bg-white dark:bg-gray-dark-100 py-2 my-6 rounded">
|
||||
<button class="not-prose w-full py-2 px-4 flex justify-between" x-on:click="open = ! open">
|
||||
<span>{{ .title }}</span>
|
||||
<div class="{{ with .large }} text-xl {{ end }} flex items-center gap-2">
|
||||
{{- with .icon }}
|
||||
<span class="icon-svg -mt-1">{{ partialCached "icon" . . }}</span>
|
||||
{{- end }}
|
||||
{{ .title }}
|
||||
</div>
|
||||
<span :class="{ 'hidden' : !open }" class="icon-svg">{{ partialCached "icon" "expand_less" "expand_less" }}</span>
|
||||
<span :class="{ 'hidden' : open }" class="icon-svg">{{ partialCached "icon" "expand_more" "expand_more" }}</span>
|
||||
</button>
|
||||
|
||||
<div x-show="open" x-collapse class="px-4">
|
||||
{{ .body | .page.RenderString (dict "display" "block") }}
|
||||
{{ markdownify .body }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<div class="not-prose">
|
||||
<div class="flex flex-col sm:flex-row gap-4 p-6 m-4 bg-gray-light-200 dark:bg-gray-dark-300">
|
||||
<div class="flex-grow flex flex-col sm:items-center">
|
||||
<span><strong>Skill level</strong></span>
|
||||
<span>{{ .Params.skill }}</span>
|
||||
</div>
|
||||
<div class="flex-grow flex flex-col sm:items-center">
|
||||
<span><strong>Time to complete</strong></span>
|
||||
<span>{{ .Params.time }}</span>
|
||||
</div>
|
||||
<div class="flex-grow flex flex-col sm:items-center">
|
||||
<span><strong>Prerequisites</strong></span>
|
||||
<span>{{ .Params.prereq }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,13 @@
|
|||
<div class="not-prose gap-12 py-4 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{{ range . }}
|
||||
<div class="flex flex-col">
|
||||
<a class="hover:underline" href="{{ .Permalink }}">
|
||||
{{- $img := resources.Get .Params.image }}
|
||||
{{- $img = $img.Process "resize 600x" }}
|
||||
<img class="h-48 w-full object-cover rounded shadow" src="{{ $img.Permalink }}">
|
||||
<p class="text-xl leading-snug my-4">{{ .Title }}</p>
|
||||
</a>
|
||||
<p class="text-sm">{{ .Summary }} <a class="link" href="{{ .Permalink }}">Read more</a></p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
|
@ -0,0 +1,51 @@
|
|||
<script>
|
||||
(function() {
|
||||
var tag = document.createElement('script');
|
||||
tag.id = "youtube-iframe-api";
|
||||
tag.src = "https://www.youtube.com/iframe_api";
|
||||
var firstScriptTag = document.getElementsByTagName('script')[0];
|
||||
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
||||
|
||||
window.onYouTubeIframeAPIReady = function() {
|
||||
var youtubeDivs = document.querySelectorAll(".youtube-video");
|
||||
for (var i = 0; i < youtubeDivs.length; i++) {
|
||||
createPlayer(youtubeDivs[i].id, youtubeDivs[i].dataset.videoId);
|
||||
}
|
||||
}
|
||||
|
||||
function createPlayer(domElementId, videoId) {
|
||||
new YT.Player(domElementId, {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
videoId: videoId,
|
||||
playerVars: {
|
||||
'rel': 0,
|
||||
'iv_load_policy': 3,
|
||||
'enablejsapi': 1,
|
||||
'origin': window.location.origin
|
||||
},
|
||||
events: {
|
||||
'onStateChange': function (event) {
|
||||
onPlayerStateChange(event, videoId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onPlayerStateChange(event, videoId) {
|
||||
if (window.heap === undefined) return;
|
||||
|
||||
var properties = {
|
||||
video_id: videoId,
|
||||
page_path: window.location.pathname,
|
||||
page_title: document.title,
|
||||
};
|
||||
|
||||
if (event.data == YT.PlayerState.PLAYING) {
|
||||
heap.track("Video Play", properties);
|
||||
} else if (event.data == YT.PlayerState.PAUSED) {
|
||||
heap.track("Video Paused", properties);
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
|
@ -1,3 +1,13 @@
|
|||
{{ $title := .Get "title" }}
|
||||
{{ $body := .Inner }}
|
||||
{{ partial "components/accordion.html" (dict "title" $title "body" $body "page" .Page) }}
|
||||
{{ $icon := .Get "icon" }}
|
||||
{{ $open := .Get "open" }}
|
||||
{{ $large := .Get "large" }}
|
||||
{{ $body := .InnerDeindent }}
|
||||
{{ partial "components/accordion.html"
|
||||
(dict "title" $title
|
||||
"body" $body
|
||||
"icon" $icon
|
||||
"open" $open
|
||||
"large" $large
|
||||
)
|
||||
}}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
{{ $cols := strings.Split .InnerDeindent "<!-- break -->" }}
|
||||
<div class="md:flex gap-8">
|
||||
{{ range $cols }}
|
||||
<div class="flex-1">
|
||||
{{ markdownify . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
|
@ -1,2 +1,2 @@
|
|||
{{- .Page.Store.Set "youtube" true -}}
|
||||
<div id="youtube-player-{{ .Get 0 }}" data-video-id="{{ .Get 0 }}" class="youtube-video aspect-video w-full"></div>
|
||||
<div id="youtube-player-{{ .Get 0 }}" data-video-id="{{ .Get 0 }}" class="youtube-video aspect-video w-full py-2"></div>
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
</div>
|
||||
</main>
|
||||
<footer class="mt-auto">{{ partialCached "footer.html" . }}</footer>
|
||||
{{/* Load the YouTube player if the page embeds a YouTube video */}}
|
||||
{{ with .Store.Get "youtube" }}
|
||||
{{- partial "youtube-script.html" . }}
|
||||
{{ end }}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
Loading…
Reference in New Issue