mirror of
https://github.com/docker/docs.git
synced 2026-10-23 18:09:02 +03:00
Revamp the guides section: taxonomy, single-page structure, and new landing/filter UX (#25338)
## What A full revamp of the `/guides` section — taxonomy, structure, and UX. Preview: https://deploy-preview-25338--docsdocker.netlify.app/guides/ ### Taxonomy & structure - Replaces the sprawling 24-tag set with a focused 9-tag taxonomy aligned to use case / SDLC: **Languages & frameworks, AI, Testing, CI/CD, Security, Databases, Deployment, Admin, Hands-on labs**. - Removes the languages taxonomy entirely (`data/languages.yaml` and all `languages:` front matter). - Collapses all multi-page guide series into single pages, with aliases so old sub-page URLs continue to resolve. - Deletes redirect-only shim pages and flattens directory-wrapped single pages. ### Landing page (`/guides/`) - A clean index: hero, then category sections listing each guide as a plain **title / summary** row. - **Browse rail** (sticky, left): click a topic to filter the page to just that topic's guides; "All guides" resets. A count + Clear bar appears while filtering. - **Text filter**: instant client-side search over title, summary, and tags. Topic filter and text search are mutually exclusive and share the same flat-list view. - No more "Featured guides" section. ### Guide content pages - Removes the left sidebar for the guides section (mobile drawer kept). - Centered reading column (`92ch`) with the TOC taking the remaining width. - Summary rendered as a lead paragraph under the h1. - TOC scrollbar auto-hides until hover; breadcrumbs render at a consistent size inside and outside `prose`. ## Notes - Deep full-text search across guide bodies is still handled by the existing site-wide Pagefind (⌘K); the landing filter is the fast metadata-narrowing surface. - `series.html` is retained — it's still used by `get-started` pages. ## Validation - Site builds clean locally (Hugo dev server, no errors / broken refs). - All collapsed sub-page URLs redirect via aliases. ## Follow-ups - Prune guides that we no longer need/want - Tighten the guides that span too many concepts (e.g. language guides; remove cicd/deploy/sscs) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -208,6 +208,33 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@utility scrollbar-hover {
|
||||
/* Firefox: hide the thumb until hover */
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: transparent transparent;
|
||||
&:hover {
|
||||
scrollbar-color: var(--color-gray-400) transparent;
|
||||
}
|
||||
.dark &:hover {
|
||||
scrollbar-color: var(--color-gray-600) transparent;
|
||||
}
|
||||
/* WebKit: reserve the track, reveal the thumb only on hover */
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
border-radius: 9999px;
|
||||
background-color: transparent;
|
||||
}
|
||||
&:hover::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-gray-400);
|
||||
}
|
||||
.dark &:hover::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-gray-600);
|
||||
}
|
||||
}
|
||||
|
||||
@utility chip {
|
||||
@apply border-divider-light dark:border-divider-dark inline-flex items-center gap-1 rounded-full border bg-gray-100 px-2 text-sm text-gray-800 select-none dark:bg-gray-700 dark:text-gray-200;
|
||||
}
|
||||
@@ -217,7 +244,17 @@
|
||||
}
|
||||
|
||||
@utility breadcrumbs {
|
||||
font-size: 90%;
|
||||
/* Absolute size so breadcrumbs render identically inside and outside prose */
|
||||
font-size: calc(var(--text-base) * 0.9);
|
||||
}
|
||||
|
||||
/* Guides landing: collapse section spacing into a flat list while filtering.
|
||||
Grouped spacing is the static default; this only applies once the page is
|
||||
being filtered, so it never affects first paint (no layout jank). */
|
||||
.guides-flat > section {
|
||||
border-top-width: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
@utility topbar-button {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Docker guides
|
||||
linkTitle: Guides
|
||||
description: Explore the Docker guides
|
||||
description: Step-by-step tutorials, organized by what you're trying to do.
|
||||
keywords: docker, guides, tutorials, learning paths, getting started
|
||||
params:
|
||||
icon: book-open
|
||||
@@ -9,13 +9,17 @@ layout: landing
|
||||
aliases:
|
||||
- /guides/language/
|
||||
- /language/
|
||||
- /guides/dhi-from-doi/
|
||||
- /guides/dhi-from-wolfi/
|
||||
- /guides/dhi-go-example/
|
||||
- /guides/dhi-nodejs-example/
|
||||
- /guides/dhi-python-example/
|
||||
- /guides/lab-docker-for-ai-redirect/
|
||||
- /learning-paths/
|
||||
---
|
||||
|
||||
Explore our collection of guides to learn how Docker can optimize your
|
||||
development workflows and how to use it with specific languages, frameworks, or
|
||||
technologies.
|
||||
Explore guides to learn how Docker can optimize your development workflows and
|
||||
how to use it with specific languages, frameworks, or technologies.
|
||||
|
||||
Can't find the guide you're looking for? Open an issue on the
|
||||
[docker/docs](https://github.com/docker/docs/issues/new) repository to let us
|
||||
know.
|
||||
[docker/docs](https://github.com/docker/docs/issues/new) repository.
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
---
|
||||
title: Set up your company for success with Docker
|
||||
linkTitle: Admin set up
|
||||
summary: Get the most out of Docker by streamlining workflows, standardizing development environments, and ensuring smooth deployments across your company.
|
||||
description: Learn how to onboard your company and take advantage of all of the Docker products and features.
|
||||
keywords: admin, onboarding, deployment, organization setup, docker business, rollout
|
||||
tags: [admin]
|
||||
params:
|
||||
time: 20 minutes
|
||||
image:
|
||||
resource_links:
|
||||
- title: Overview of Administration in Docker
|
||||
url: /admin/
|
||||
- title: Single sign-on
|
||||
url: /security/for-admins/single-sign-on/
|
||||
- title: Enforce sign-in
|
||||
url: /security/for-admins/enforce-sign-in/
|
||||
- title: Roles and permissions
|
||||
url: /security/for-admins/roles-and-permissions/
|
||||
- title: Settings Management
|
||||
url: /security/for-admins/hardened-desktop/settings-management/
|
||||
- title: Registry Access Management
|
||||
url: /security/for-admins/hardened-desktop/registry-access-management/
|
||||
- title: Image Access Management
|
||||
url: /security/for-admins/hardened-desktop/image-access-management/
|
||||
- title: Docker subscription information
|
||||
url: "https://www.docker.com/pricing?ref=Docs&refAction=DocsGuidesAdminSetup"
|
||||
---
|
||||
|
||||
Docker's tools provide a scalable, secure platform that empowers your
|
||||
developers to create, ship, and run applications faster. As an administrator,
|
||||
you can streamline workflows, standardize development environments, and ensure
|
||||
smooth deployments across your organization.
|
||||
|
||||
By configuring Docker products to suit your company's needs, you can optimize
|
||||
performance, simplify user management, and maintain control over resources.
|
||||
This guide helps you set up and configure Docker products to maximize
|
||||
productivity and success for your team while meeting compliance and security
|
||||
policies.
|
||||
|
||||
## Who’s this for?
|
||||
|
||||
- Administrators responsible for managing Docker environments within their
|
||||
organization
|
||||
- IT leaders looking to streamline development and deployment workflows
|
||||
- Teams aiming to standardize application environments across multiple users
|
||||
- Organizations seeking to optimize their use of Docker products for greater
|
||||
scalability and efficiency
|
||||
- Organizations with a
|
||||
[Docker Business subscription](https://www.docker.com/pricing?ref=DocsGuides&refAction=DocsGuidesCTAClicked)
|
||||
|
||||
## What you’ll learn
|
||||
|
||||
- Why signing into your company's Docker organization provides access to usage
|
||||
data and enhanced functionality
|
||||
- How to standardize Docker Desktop versions and settings to create a consistent
|
||||
baseline for all users, while allowing flexibility for advanced developers
|
||||
- Strategies for implementing Docker's security configurations to meet company
|
||||
IT and software development security requirements without hindering developer productivity
|
||||
|
||||
## Features covered
|
||||
|
||||
This guide covers the following Docker features:
|
||||
|
||||
- [Organizations](/manuals/admin/organization/_index.md): The core structure
|
||||
for managing your Docker environment, grouping users, teams, and image
|
||||
repositories. Your organization was created with your subscription and is
|
||||
managed by one or more owners. Users signed into the organization are
|
||||
assigned seats based on the purchased subscription.
|
||||
- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md):
|
||||
By default, Docker Desktop doesn't require sign-in. You can configure
|
||||
settings to enforce this and ensure your developers sign in to your
|
||||
Docker organization.
|
||||
- [SSO](/manuals/enterprise/security/single-sign-on/_index.md): Without SSO,
|
||||
user management in a Docker organization is manual. Setting
|
||||
up an SSO connection between your identity provider and Docker ensures
|
||||
compliance with your security policy and automates user provisioning. Adding
|
||||
SCIM further automates user provisioning and de-provisioning.
|
||||
- General and security settings: Configuring key settings ensures smooth
|
||||
onboarding and usage of Docker products within your environment. You can also
|
||||
enable security features based on your company's specific security needs.
|
||||
|
||||
## Who needs to be involved
|
||||
|
||||
- Docker organization owner: Must be involved in the process and is required
|
||||
for several key steps
|
||||
- DNS team: Needed during the SSO setup to verify the company domain
|
||||
- MDM team: Responsible for distributing Docker-specific configuration files to
|
||||
developer machines
|
||||
- Identity Provider team: Required for configuring the identity provider and
|
||||
establishing the SSO connection during setup
|
||||
- Development lead: A development lead with knowledge of Docker configurations
|
||||
to help establish a baseline for developer settings
|
||||
- IT team: An IT representative familiar with company desktop policies to
|
||||
assist with aligning Docker configuration to those policies
|
||||
- Infosec: A security team member with knowledge of company development
|
||||
security policies to help configure security features
|
||||
- Docker testers: A small group of developers to test the new settings and
|
||||
configurations before full deployment
|
||||
|
||||
## Tools integration
|
||||
|
||||
This guide covers integration with:
|
||||
|
||||
- Okta
|
||||
- Entra ID SAML 2.0
|
||||
- Azure Connect (OIDC)
|
||||
- MDM solutions like Intune
|
||||
@@ -1,75 +0,0 @@
|
||||
---
|
||||
title: Communication and information gathering
|
||||
description: Gather your company's requirements from key stakeholders and communicate to your developers.
|
||||
keywords: admin, onboarding, stakeholders, communication, mdm, requirements
|
||||
weight: 10
|
||||
---
|
||||
|
||||
## Communicate with your developers and IT teams
|
||||
|
||||
Before rolling out Docker Desktop across your organization, coordinate with key stakeholders to ensure a smooth transition.
|
||||
|
||||
### Notify Docker Desktop users
|
||||
|
||||
You may already have Docker Desktop users within your company. Some steps in
|
||||
this onboarding process may affect how they interact with the platform.
|
||||
|
||||
Communicate early with users to inform them that:
|
||||
|
||||
- They'll be upgraded to a supported version of Docker Desktop as part of the subscription onboarding
|
||||
- Settings will be reviewed and optimized for productivity
|
||||
- They'll need to sign in to the company's Docker organization using their
|
||||
business email to access subscription benefits
|
||||
|
||||
### Engage with your MDM team
|
||||
|
||||
Device management solutions, such as Intune and Jamf, are commonly used for
|
||||
software distribution across enterprises. These tools are typically managed by a dedicated MDM team.
|
||||
|
||||
Engage with this team early in the process to:
|
||||
|
||||
- Understand their requirements and lead time for deploying changes
|
||||
- Coordinate the distribution of configuration files
|
||||
|
||||
Several setup steps in this guide require JSON files, registry keys, or .plist
|
||||
files to be distributed to developer machines. Use MDM tools to deploy these configuration files and ensure their integrity.
|
||||
|
||||
## Identify Docker organizations
|
||||
|
||||
Some companies may have more than one
|
||||
[Docker organization](/manuals/admin/organization/_index.md) created. These
|
||||
organizations may have been created for specific purposes, or may not be
|
||||
needed anymore.
|
||||
|
||||
If you suspect your company has multiple Docker organizations:
|
||||
|
||||
- Survey your teams to see if they have their own organizations
|
||||
- Contact your Docker Support to get a list of organizations with users whose
|
||||
emails match your domain name
|
||||
|
||||
## Gather requirements
|
||||
|
||||
[Settings Management](/manuals/enterprise/security/hardened-desktop/settings-management/_index.md) lets you preset numerous configuration parameters for Docker Desktop.
|
||||
|
||||
Work with the following stakeholders to establish your company's baseline
|
||||
configuration:
|
||||
|
||||
- Docker organization owner
|
||||
- Development lead
|
||||
- Information security representative
|
||||
|
||||
Review these areas together:
|
||||
|
||||
- Security features and
|
||||
[enforcing sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md)
|
||||
for Docker Desktop users
|
||||
- Additional Docker products included in your subscriptions
|
||||
|
||||
To view the parameters that can be preset, see [Configure Settings Management](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md#step-two-configure-the-settings-you-want-to-lock-in).
|
||||
|
||||
## Optional: Meet with the Docker Implementation team
|
||||
|
||||
The Docker Implementation team can help you set up your organization,
|
||||
configure SSO, enforce sign-in, and configure Docker Desktop.
|
||||
|
||||
To schedule a meeting, email successteam@docker.com.
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: Deploy your Docker setup
|
||||
description: Deploy your Docker setup across your company.
|
||||
keywords: admin, onboarding, deployment, sso, rollout, organization
|
||||
weight: 40
|
||||
---
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Communicate with your users before proceeding, and confirm that your IT and
|
||||
> MDM teams are prepared to handle any unexpected issues, as these steps will
|
||||
> affect all existing users signing into your Docker organization.
|
||||
|
||||
## Enforce SSO
|
||||
|
||||
Enforcing SSO means that anyone who has a Docker profile with an email address
|
||||
that matches your verified domain must sign in using your SSO connection. Make
|
||||
sure the Identity provider groups associated with your SSO connection cover all
|
||||
the developer groups that you want to have access to the Docker subscription.
|
||||
|
||||
For instructions on how to enforce SSO, see [Enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md).
|
||||
|
||||
## Deploy configuration settings and enforce sign-in to users
|
||||
|
||||
Have the MDM team deploy the configuration files for Docker to all users.
|
||||
|
||||
## Next steps
|
||||
|
||||
Congratulations, you've successfully completed the admin implementation process
|
||||
for Docker.
|
||||
|
||||
To continue optimizing your Docker environment:
|
||||
|
||||
- Review your [organization's usage data](/manuals/admin/insights.md) to track adoption
|
||||
- Monitor [Docker Scout findings](/manuals/scout/explore/analysis.md) for security insights
|
||||
- Explore [additional security features](/manuals/enterprise/security/_index.md) to enhance your configuration
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
title: Finalize plans and begin setup
|
||||
description: Collaborate with your MDM team to distribute configurations and set up SSO and Docker product trials.
|
||||
keywords: admin, onboarding, mdm, settings management, sso, configuration
|
||||
weight: 20
|
||||
---
|
||||
|
||||
## Send finalized settings files to the MDM team
|
||||
|
||||
After reaching an agreement with the relevant teams about your baseline and
|
||||
security configurations as outlined in the previous section, configure Settings Management using either the [Docker Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) or an
|
||||
[`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md).
|
||||
|
||||
Once the file is ready, collaborate with your MDM team to deploy your chosen
|
||||
settings, along with your chosen method for [enforcing sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md).
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Test this first with a small number of Docker Desktop developers to verify the functionality works as expected before deploying more widely.
|
||||
|
||||
## Manage your organizations
|
||||
|
||||
If you have more than one organization, consider either [consolidating them
|
||||
into one organization](/manuals/admin/organization/setup/orgs.md) or creating a
|
||||
[Docker company](/manuals/admin/company/_index.md) to manage multiple
|
||||
organizations.
|
||||
|
||||
## Begin setup
|
||||
|
||||
### Set up single sign-on and domain verification
|
||||
|
||||
Single sign-on (SSO) lets developers authenticate using their identity
|
||||
providers (IdPs) to access Docker. SSO is available for a whole company and all associated organizations, or an individual organization that has a Docker
|
||||
Business subscription. For more information, see the
|
||||
[documentation](/manuals/enterprise/security/single-sign-on/_index.md).
|
||||
|
||||
You can also enable [SCIM](/manuals/enterprise/security/provisioning/scim/_index.md)
|
||||
for further automation of provisioning and deprovisioning of users.
|
||||
|
||||
### Set up Docker product entitlements included in the subscription
|
||||
|
||||
[Docker Build Cloud](/manuals/build-cloud/_index.md) significantly reduces
|
||||
build times, both locally and in CI, by providing a dedicated remote builder
|
||||
and shared cache. Powered by the cloud, developer time and local resources are
|
||||
freed up so your team can focus on more important things, like innovation.
|
||||
To get started, [set up a cloud builder](https://app.docker.com/build/).
|
||||
|
||||
[Docker Scout](manuals/scout/_index.md) is a solution for proactively enhancing
|
||||
your software supply chain security. By analyzing your images, Docker Scout
|
||||
compiles an inventory of components, also known as a Software Bill of Materials
|
||||
(SBOM). The SBOM is matched against a continuously updated vulnerability
|
||||
database to pinpoint security weaknesses. To get started, see
|
||||
[Quickstart](/manuals/scout/quickstart.md).
|
||||
|
||||
[Testcontainers Cloud](https://testcontainers.com/cloud/docs/) allows
|
||||
developers to run containers in the cloud, removing the need to run heavy
|
||||
containers on your local machine.
|
||||
|
||||
[Docker Hardened Images](/manuals/dhi/_index.md) are minimal, secure, and production-ready container base and application images maintained by Docker.
|
||||
Designed to reduce vulnerabilities and simplify compliance, DHIs integrate
|
||||
easily into your existing Docker-based workflows with little to no retooling
|
||||
required.
|
||||
|
||||
### Ensure you're running a supported version of Docker Desktop
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> This step could affect the experience for users on older versions of Docker
|
||||
> Desktop.
|
||||
|
||||
Existing users may be running outdated or unsupported versions of
|
||||
Docker Desktop. All users should update to a supported version. Docker Desktop
|
||||
versions released within the past 6 months from the latest release are supported.
|
||||
|
||||
Use an MDM solution to manage the version of Docker Desktop for users. Users
|
||||
may also get Docker Desktop directly from Docker or through a company software
|
||||
portal.
|
||||
330
content/guides/admin-set-up/index.md
Normal file
330
content/guides/admin-set-up/index.md
Normal file
@@ -0,0 +1,330 @@
|
||||
---
|
||||
title: Set up your company for success with Docker
|
||||
linkTitle: Admin set up
|
||||
summary: Get the most out of Docker by streamlining workflows, standardizing development environments, and ensuring smooth deployments across your company.
|
||||
description: Learn how to onboard your company and take advantage of all of the Docker products and features.
|
||||
keywords: admin, onboarding, deployment, organization setup, docker business, rollout
|
||||
aliases:
|
||||
- /guides/admin-set-up/comms-and-info-gathering/
|
||||
- /guides/admin-set-up/deploy/
|
||||
- /guides/admin-set-up/finalize-plans-and-setup/
|
||||
- /guides/admin-set-up/testing/
|
||||
params:
|
||||
tags: [admin]
|
||||
time: 20 minutes
|
||||
image:
|
||||
---
|
||||
|
||||
|
||||
Docker's tools provide a scalable, secure platform that empowers your
|
||||
developers to create, ship, and run applications faster. As an administrator,
|
||||
you can streamline workflows, standardize development environments, and ensure
|
||||
smooth deployments across your organization.
|
||||
|
||||
By configuring Docker products to suit your company's needs, you can optimize
|
||||
performance, simplify user management, and maintain control over resources.
|
||||
This guide helps you set up and configure Docker products to maximize
|
||||
productivity and success for your team while meeting compliance and security
|
||||
policies.
|
||||
|
||||
## Who’s this for?
|
||||
|
||||
- Administrators responsible for managing Docker environments within their
|
||||
organization
|
||||
- IT leaders looking to streamline development and deployment workflows
|
||||
- Teams aiming to standardize application environments across multiple users
|
||||
- Organizations seeking to optimize their use of Docker products for greater
|
||||
scalability and efficiency
|
||||
- Organizations with a
|
||||
[Docker Business subscription](https://www.docker.com/pricing?ref=DocsGuides&refAction=DocsGuidesCTAClicked)
|
||||
|
||||
## What you’ll learn
|
||||
|
||||
- Why signing into your company's Docker organization provides access to usage
|
||||
data and enhanced functionality
|
||||
- How to standardize Docker Desktop versions and settings to create a consistent
|
||||
baseline for all users, while allowing flexibility for advanced developers
|
||||
- Strategies for implementing Docker's security configurations to meet company
|
||||
IT and software development security requirements without hindering developer productivity
|
||||
|
||||
## Features covered
|
||||
|
||||
This guide covers the following Docker features:
|
||||
|
||||
- [Organizations](/manuals/admin/organization/_index.md): The core structure
|
||||
for managing your Docker environment, grouping users, teams, and image
|
||||
repositories. Your organization was created with your subscription and is
|
||||
managed by one or more owners. Users signed into the organization are
|
||||
assigned seats based on the purchased subscription.
|
||||
- [Enforce sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md):
|
||||
By default, Docker Desktop doesn't require sign-in. You can configure
|
||||
settings to enforce this and ensure your developers sign in to your
|
||||
Docker organization.
|
||||
- [SSO](/manuals/enterprise/security/single-sign-on/_index.md): Without SSO,
|
||||
user management in a Docker organization is manual. Setting
|
||||
up an SSO connection between your identity provider and Docker ensures
|
||||
compliance with your security policy and automates user provisioning. Adding
|
||||
SCIM further automates user provisioning and de-provisioning.
|
||||
- General and security settings: Configuring key settings ensures smooth
|
||||
onboarding and usage of Docker products within your environment. You can also
|
||||
enable security features based on your company's specific security needs.
|
||||
|
||||
## Who needs to be involved
|
||||
|
||||
- Docker organization owner: Must be involved in the process and is required
|
||||
for several key steps
|
||||
- DNS team: Needed during the SSO setup to verify the company domain
|
||||
- MDM team: Responsible for distributing Docker-specific configuration files to
|
||||
developer machines
|
||||
- Identity Provider team: Required for configuring the identity provider and
|
||||
establishing the SSO connection during setup
|
||||
- Development lead: A development lead with knowledge of Docker configurations
|
||||
to help establish a baseline for developer settings
|
||||
- IT team: An IT representative familiar with company desktop policies to
|
||||
assist with aligning Docker configuration to those policies
|
||||
- Infosec: A security team member with knowledge of company development
|
||||
security policies to help configure security features
|
||||
- Docker testers: A small group of developers to test the new settings and
|
||||
configurations before full deployment
|
||||
|
||||
## Tools integration
|
||||
|
||||
This guide covers integration with:
|
||||
|
||||
- Okta
|
||||
- Entra ID SAML 2.0
|
||||
- Azure Connect (OIDC)
|
||||
- MDM solutions like Intune
|
||||
|
||||
## Communication and information gathering
|
||||
|
||||
### Communicate with your developers and IT teams
|
||||
|
||||
Before rolling out Docker Desktop across your organization, coordinate with key stakeholders to ensure a smooth transition.
|
||||
|
||||
#### Notify Docker Desktop users
|
||||
|
||||
You may already have Docker Desktop users within your company. Some steps in
|
||||
this onboarding process may affect how they interact with the platform.
|
||||
|
||||
Communicate early with users to inform them that:
|
||||
|
||||
- They'll be upgraded to a supported version of Docker Desktop as part of the subscription onboarding
|
||||
- Settings will be reviewed and optimized for productivity
|
||||
- They'll need to sign in to the company's Docker organization using their
|
||||
business email to access subscription benefits
|
||||
|
||||
#### Engage with your MDM team
|
||||
|
||||
Device management solutions, such as Intune and Jamf, are commonly used for
|
||||
software distribution across enterprises. These tools are typically managed by a dedicated MDM team.
|
||||
|
||||
Engage with this team early in the process to:
|
||||
|
||||
- Understand their requirements and lead time for deploying changes
|
||||
- Coordinate the distribution of configuration files
|
||||
|
||||
Several setup steps in this guide require JSON files, registry keys, or .plist
|
||||
files to be distributed to developer machines. Use MDM tools to deploy these configuration files and ensure their integrity.
|
||||
|
||||
### Identify Docker organizations
|
||||
|
||||
Some companies may have more than one
|
||||
[Docker organization](/manuals/admin/organization/_index.md) created. These
|
||||
organizations may have been created for specific purposes, or may not be
|
||||
needed anymore.
|
||||
|
||||
If you suspect your company has multiple Docker organizations:
|
||||
|
||||
- Survey your teams to see if they have their own organizations
|
||||
- Contact your Docker Support to get a list of organizations with users whose
|
||||
emails match your domain name
|
||||
|
||||
### Gather requirements
|
||||
|
||||
[Settings Management](/manuals/enterprise/security/hardened-desktop/settings-management/_index.md) lets you preset numerous configuration parameters for Docker Desktop.
|
||||
|
||||
Work with the following stakeholders to establish your company's baseline
|
||||
configuration:
|
||||
|
||||
- Docker organization owner
|
||||
- Development lead
|
||||
- Information security representative
|
||||
|
||||
Review these areas together:
|
||||
|
||||
- Security features and
|
||||
[enforcing sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md)
|
||||
for Docker Desktop users
|
||||
- Additional Docker products included in your subscriptions
|
||||
|
||||
To view the parameters that can be preset, see [Configure Settings Management](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md#step-two-configure-the-settings-you-want-to-lock-in).
|
||||
|
||||
### Optional: Meet with the Docker Implementation team
|
||||
|
||||
The Docker Implementation team can help you set up your organization,
|
||||
configure SSO, enforce sign-in, and configure Docker Desktop.
|
||||
|
||||
To schedule a meeting, email successteam@docker.com.
|
||||
|
||||
## Finalize plans and begin setup
|
||||
|
||||
### Send finalized settings files to the MDM team
|
||||
|
||||
After reaching an agreement with the relevant teams about your baseline and
|
||||
security configurations as outlined in the previous section, configure Settings Management using either the [Docker Admin Console](/manuals/enterprise/security/hardened-desktop/settings-management/configure-admin-console.md) or an
|
||||
[`admin-settings.json` file](/manuals/enterprise/security/hardened-desktop/settings-management/configure-json-file.md).
|
||||
|
||||
Once the file is ready, collaborate with your MDM team to deploy your chosen
|
||||
settings, along with your chosen method for [enforcing sign-in](/manuals/enterprise/security/enforce-sign-in/_index.md).
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Test this first with a small number of Docker Desktop developers to verify the functionality works as expected before deploying more widely.
|
||||
|
||||
### Manage your organizations
|
||||
|
||||
If you have more than one organization, consider either [consolidating them
|
||||
into one organization](/manuals/admin/organization/setup/orgs.md) or creating a
|
||||
[Docker company](/manuals/admin/company/_index.md) to manage multiple
|
||||
organizations.
|
||||
|
||||
### Begin setup
|
||||
|
||||
#### Set up single sign-on and domain verification
|
||||
|
||||
Single sign-on (SSO) lets developers authenticate using their identity
|
||||
providers (IdPs) to access Docker. SSO is available for a whole company and all associated organizations, or an individual organization that has a Docker
|
||||
Business subscription. For more information, see the
|
||||
[documentation](/manuals/enterprise/security/single-sign-on/_index.md).
|
||||
|
||||
You can also enable [SCIM](/manuals/enterprise/security/provisioning/scim/_index.md)
|
||||
for further automation of provisioning and deprovisioning of users.
|
||||
|
||||
#### Set up Docker product entitlements included in the subscription
|
||||
|
||||
[Docker Build Cloud](/manuals/build-cloud/_index.md) significantly reduces
|
||||
build times, both locally and in CI, by providing a dedicated remote builder
|
||||
and shared cache. Powered by the cloud, developer time and local resources are
|
||||
freed up so your team can focus on more important things, like innovation.
|
||||
To get started, [set up a cloud builder](https://app.docker.com/build/).
|
||||
|
||||
[Docker Scout](manuals/scout/_index.md) is a solution for proactively enhancing
|
||||
your software supply chain security. By analyzing your images, Docker Scout
|
||||
compiles an inventory of components, also known as a Software Bill of Materials
|
||||
(SBOM). The SBOM is matched against a continuously updated vulnerability
|
||||
database to pinpoint security weaknesses. To get started, see
|
||||
[Quickstart](/manuals/scout/quickstart.md).
|
||||
|
||||
[Testcontainers Cloud](https://testcontainers.com/cloud/docs/) allows
|
||||
developers to run containers in the cloud, removing the need to run heavy
|
||||
containers on your local machine.
|
||||
|
||||
[Docker Hardened Images](/manuals/dhi/_index.md) are minimal, secure, and production-ready container base and application images maintained by Docker.
|
||||
Designed to reduce vulnerabilities and simplify compliance, DHIs integrate
|
||||
easily into your existing Docker-based workflows with little to no retooling
|
||||
required.
|
||||
|
||||
#### Ensure you're running a supported version of Docker Desktop
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> This step could affect the experience for users on older versions of Docker
|
||||
> Desktop.
|
||||
|
||||
Existing users may be running outdated or unsupported versions of
|
||||
Docker Desktop. All users should update to a supported version. Docker Desktop
|
||||
versions released within the past 6 months from the latest release are supported.
|
||||
|
||||
Use an MDM solution to manage the version of Docker Desktop for users. Users
|
||||
may also get Docker Desktop directly from Docker or through a company software
|
||||
portal.
|
||||
|
||||
## Testing
|
||||
|
||||
### SSO and SCIM testing
|
||||
|
||||
Test SSO and SCIM by signing in to Docker Desktop or Docker Hub with the email
|
||||
address linked to a Docker account that is part of the verified domain.
|
||||
Developers who sign in using their Docker usernames remain unaffected by the
|
||||
SSO and SCIM setup.
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Some users may need CLI based logins to Docker Hub, and for this they will
|
||||
> need a [personal access token (PAT)](/manuals/security/access-tokens.md).
|
||||
|
||||
### Test Registry Access Management and Image Access Management
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Communicate with your users before proceeding, as this step will impact all
|
||||
> existing users signing into your Docker organization.
|
||||
|
||||
If you plan to use [Registry Access Management (RAM)](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) and/or [Image Access Management (IAM)](/manuals/enterprise/security/hardened-desktop/image-access-management.md):
|
||||
|
||||
1. Ensure your test developer signs in to Docker Desktop using their
|
||||
organization credentials
|
||||
2. Have them attempt to pull an unauthorized image or one from a disallowed
|
||||
registry via the Docker CLI
|
||||
3. Verify they receive an error message indicating that the registry is
|
||||
restricted by the organization
|
||||
|
||||
### Deploy settings and enforce sign in to test group
|
||||
|
||||
Deploy the Docker settings and enforce sign-in for a small group of test users
|
||||
via MDM. Have this group test their development workflows with containers on
|
||||
Docker Desktop and Docker Hub to ensure all settings and the sign-in enforcement
|
||||
function as expected.
|
||||
|
||||
### Test Docker Build Cloud capabilities
|
||||
|
||||
Have one of your Docker Desktop testers [connect to the cloud builder you created and use it to build](/manuals/build-cloud/usage.md).
|
||||
|
||||
### Test Testcontainers Cloud
|
||||
|
||||
Have a test developer [connect to Testcontainers Cloud](https://testcontainers.com/cloud/docs/#getting-started) and run a container in
|
||||
the cloud to verify the setup is working correctly.
|
||||
|
||||
### Verify Docker Scout monitoring of repositories
|
||||
|
||||
Check the [Docker Scout dashboard](https://scout.docker.com/) to confirm that
|
||||
data is being properly received for the repositories where Docker Scout has
|
||||
been enabled.
|
||||
|
||||
### Verify access to Docker Hardened Images
|
||||
|
||||
Have a test developer attempt to [pull a Docker Hardened Image](/manuals/dhi/get-started.md) to confirm that
|
||||
the team has proper access and can integrate these images into their workflows.
|
||||
|
||||
## Deploy your Docker setup
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Communicate with your users before proceeding, and confirm that your IT and
|
||||
> MDM teams are prepared to handle any unexpected issues, as these steps will
|
||||
> affect all existing users signing into your Docker organization.
|
||||
|
||||
### Enforce SSO
|
||||
|
||||
Enforcing SSO means that anyone who has a Docker profile with an email address
|
||||
that matches your verified domain must sign in using your SSO connection. Make
|
||||
sure the Identity provider groups associated with your SSO connection cover all
|
||||
the developer groups that you want to have access to the Docker subscription.
|
||||
|
||||
For instructions on how to enforce SSO, see [Enforce SSO](/manuals/enterprise/security/single-sign-on/connect.md).
|
||||
|
||||
### Deploy configuration settings and enforce sign-in to users
|
||||
|
||||
Have the MDM team deploy the configuration files for Docker to all users.
|
||||
|
||||
### Next steps
|
||||
|
||||
Congratulations, you've successfully completed the admin implementation process
|
||||
for Docker.
|
||||
|
||||
To continue optimizing your Docker environment:
|
||||
|
||||
- Review your [organization's usage data](/manuals/admin/insights.md) to track adoption
|
||||
- Monitor [Docker Scout findings](/manuals/scout/explore/analysis.md) for security insights
|
||||
- Explore [additional security features](/manuals/enterprise/security/_index.md) to enhance your configuration
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
title: Testing
|
||||
description: Test your Docker setup.
|
||||
keywords: admin, onboarding, testing, sso, scim, verification
|
||||
weight: 30
|
||||
---
|
||||
|
||||
## SSO and SCIM testing
|
||||
|
||||
Test SSO and SCIM by signing in to Docker Desktop or Docker Hub with the email
|
||||
address linked to a Docker account that is part of the verified domain.
|
||||
Developers who sign in using their Docker usernames remain unaffected by the
|
||||
SSO and SCIM setup.
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Some users may need CLI based logins to Docker Hub, and for this they will
|
||||
> need a [personal access token (PAT)](/manuals/security/access-tokens.md).
|
||||
|
||||
## Test Registry Access Management and Image Access Management
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Communicate with your users before proceeding, as this step will impact all
|
||||
> existing users signing into your Docker organization.
|
||||
|
||||
If you plan to use [Registry Access Management (RAM)](/manuals/enterprise/security/hardened-desktop/registry-access-management.md) and/or [Image Access Management (IAM)](/manuals/enterprise/security/hardened-desktop/image-access-management.md):
|
||||
|
||||
1. Ensure your test developer signs in to Docker Desktop using their
|
||||
organization credentials
|
||||
2. Have them attempt to pull an unauthorized image or one from a disallowed
|
||||
registry via the Docker CLI
|
||||
3. Verify they receive an error message indicating that the registry is
|
||||
restricted by the organization
|
||||
|
||||
## Deploy settings and enforce sign in to test group
|
||||
|
||||
Deploy the Docker settings and enforce sign-in for a small group of test users
|
||||
via MDM. Have this group test their development workflows with containers on
|
||||
Docker Desktop and Docker Hub to ensure all settings and the sign-in enforcement
|
||||
function as expected.
|
||||
|
||||
## Test Docker Build Cloud capabilities
|
||||
|
||||
Have one of your Docker Desktop testers [connect to the cloud builder you created and use it to build](/manuals/build-cloud/usage.md).
|
||||
|
||||
## Test Testcontainers Cloud
|
||||
|
||||
Have a test developer [connect to Testcontainers Cloud](https://testcontainers.com/cloud/docs/#getting-started) and run a container in
|
||||
the cloud to verify the setup is working correctly.
|
||||
|
||||
## Verify Docker Scout monitoring of repositories
|
||||
|
||||
Check the [Docker Scout dashboard](https://scout.docker.com/) to confirm that
|
||||
data is being properly received for the repositories where Docker Scout has
|
||||
been enabled.
|
||||
|
||||
## Verify access to Docker Hardened Images
|
||||
|
||||
Have a test developer attempt to [pull a Docker Hardened Image](/manuals/dhi/get-started.md) to confirm that
|
||||
the team has proper access and can integrate these images into their workflows.
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
title: Mastering user and access management
|
||||
summary: Simplify user access while ensuring security and efficiency in Docker.
|
||||
description: A guide for managing roles, provisioning users, and optimizing Docker access with tools like SSO and activity logs.
|
||||
keywords: admin, user management, roles, permissions, sso, provisioning, access control
|
||||
tags: [admin]
|
||||
params:
|
||||
featured: false
|
||||
time: 20 minutes
|
||||
image:
|
||||
resource_links:
|
||||
- title: Overview of Administration in Docker
|
||||
url: /admin/
|
||||
- title: Single sign-on
|
||||
url: /security/for-admins/single-sign-on/
|
||||
- title: Onboard your organization
|
||||
url: /admin/organization/setup/onboard/
|
||||
- title: Roles and permissions
|
||||
url: /security/for-admins/roles-and-permissions/
|
||||
- title: Insights
|
||||
url: /admin/insights/
|
||||
- title: Activity logs
|
||||
url: /admin/activity-logs/
|
||||
---
|
||||
|
||||
Managing roles and permissions is key to securing your Docker environment while enabling easy collaboration and operational efficiency. This guide walks IT administrators through the essentials of user and access management, offering strategies for assigning roles, provisioning users, and using tools like activity logs and Insights to monitor and optimize Docker usage.
|
||||
|
||||
## Who's this for?
|
||||
|
||||
- IT teams tasked with configuring and maintaining secure user access
|
||||
- Security professionals focused on enforcing secure access practices
|
||||
- Project managers overseeing team collaboration and resource management
|
||||
|
||||
## What you'll learn
|
||||
|
||||
- How to assess and manage Docker user access and align accounts with organizational needs
|
||||
- When to use team configurations for scalable access control
|
||||
- How to automate and streamline user provisioning with SSO, SCIM, and JIT
|
||||
- How to get the most out of Docker's monitoring tools
|
||||
|
||||
## Tools integration
|
||||
|
||||
This guide covers integration with:
|
||||
|
||||
- Okta
|
||||
- Entra ID SAML 2.0
|
||||
- Azure Connect (OIDC)
|
||||
@@ -1,54 +0,0 @@
|
||||
---
|
||||
title: Monitoring and insights
|
||||
description: Track user actions, team workflows, and organizational trends with Activity logs and Insights to enhance security and productivity in Docker.
|
||||
keywords: organizational insights, user management, access control, security, monitoring, admins
|
||||
weight: 30
|
||||
---
|
||||
|
||||
Activity logs and Insights are useful tools for user and access management in Docker. They provide visibility into user actions, team workflows, and organizational trends, helping enhance security, ensure compliance, and boost productivity.
|
||||
|
||||
## Activity logs
|
||||
|
||||
Activity logs track events at the organization and repository levels, offering a clear view of activities like repository changes, team updates, and billing adjustments.
|
||||
|
||||
Activity logs are available for Docker Team or Docker Business plans, with data retained for three months.
|
||||
|
||||
### Key features
|
||||
|
||||
- Change tracking: View what changed, who made the change, and when.
|
||||
- Comprehensive reporting: Monitor critical events such as repository creation, deletion, privacy changes, and role assignments.
|
||||
|
||||
### Example scenarios
|
||||
|
||||
- Audit trail for security: A repository’s privacy settings were updated unexpectedly. The activity logs reveal which user made the change and when, helping administrators address potential security risks.
|
||||
- Team collaboration review: Logs show which team members pushed updates to a critical repository, ensuring accountability during a development sprint.
|
||||
- Billing adjustments: Track who added or removed subscription seats to maintain budgetary control and compliance.
|
||||
|
||||
For more information, see [Activity logs](/manuals/admin/activity-logs.md).
|
||||
|
||||
## Insights
|
||||
|
||||
Insights provide data-driven views of Docker usage to improve team productivity and resource allocation.
|
||||
|
||||
### Key benefits
|
||||
|
||||
- Standardized environments: Ensure consistent configurations and enforce best practices across teams.
|
||||
- Improved visibility: Monitor metrics like Docker Desktop usage, builds, and container activity to understand team workflows and engagement.
|
||||
- Optimized resources: Track license usage and feature adoption to maximize the value of your Docker subscription.
|
||||
|
||||
### Example scenarios
|
||||
|
||||
- Usage trends: Identify underutilized licenses or resources, allowing reallocation to more active teams.
|
||||
- Build efficiency: Track average build times and success rates to pinpoint bottlenecks in development processes.
|
||||
- Container utilization: Analyze container activity across departments to ensure proper resource distribution and cost efficiency.
|
||||
|
||||
For more information, see [Insights](/manuals/admin/insights.md).
|
||||
|
||||
## Next steps
|
||||
|
||||
Now that you've mastered user and access management in Docker, you can:
|
||||
|
||||
- Review your [activity logs](/manuals/admin/activity-logs.md) regularly to maintain security awareness
|
||||
- Check your [Insights dashboard](/manuals/admin/insights.md) to identify opportunities for optimization
|
||||
- Explore [advanced security features](/manuals/enterprise/security/_index.md) to further enhance your Docker environment
|
||||
- Share best practices with your team to ensure consistent adoption of security policies
|
||||
198
content/guides/admin-user-management/index.md
Normal file
198
content/guides/admin-user-management/index.md
Normal file
@@ -0,0 +1,198 @@
|
||||
---
|
||||
title: Mastering user and access management
|
||||
summary: Simplify user access while ensuring security and efficiency in Docker.
|
||||
description: A guide for managing roles, provisioning users, and optimizing Docker access with tools like SSO and activity logs.
|
||||
keywords: admin, user management, roles, permissions, sso, provisioning, access control
|
||||
aliases:
|
||||
- /guides/admin-user-management/audit-and-monitor/
|
||||
- /guides/admin-user-management/onboard/
|
||||
- /guides/admin-user-management/setup/
|
||||
params:
|
||||
tags: [admin]
|
||||
featured: false
|
||||
time: 20 minutes
|
||||
image:
|
||||
---
|
||||
|
||||
|
||||
Managing roles and permissions is key to securing your Docker environment while enabling easy collaboration and operational efficiency. This guide walks IT administrators through the essentials of user and access management, offering strategies for assigning roles, provisioning users, and using tools like activity logs and Insights to monitor and optimize Docker usage.
|
||||
|
||||
## Who's this for?
|
||||
|
||||
- IT teams tasked with configuring and maintaining secure user access
|
||||
- Security professionals focused on enforcing secure access practices
|
||||
- Project managers overseeing team collaboration and resource management
|
||||
|
||||
## What you'll learn
|
||||
|
||||
- How to assess and manage Docker user access and align accounts with organizational needs
|
||||
- When to use team configurations for scalable access control
|
||||
- How to automate and streamline user provisioning with SSO, SCIM, and JIT
|
||||
- How to get the most out of Docker's monitoring tools
|
||||
|
||||
## Tools integration
|
||||
|
||||
This guide covers integration with:
|
||||
|
||||
- Okta
|
||||
- Entra ID SAML 2.0
|
||||
- Azure Connect (OIDC)
|
||||
|
||||
## Setting up roles and permissions in Docker
|
||||
|
||||
With the right configurations, you can ensure your developers have easy access to necessary resources while preventing unauthorized access. This page guides you through identifying Docker users so you can allocate subscription seats efficiently within your Docker organization, and assigning roles to align with your organization's structure.
|
||||
|
||||
### Identify your Docker users and accounts
|
||||
|
||||
Before setting up roles and permissions, it's important to have a clear understanding of who in your organization requires Docker access. Focus on gathering a comprehensive view of active users, their roles within projects, and how they interact with Docker resources. This process can be supported by tools like device management software or manual assessments. Encourage all users to update their Docker accounts to use organizational email addresses, ensuring seamless integration with your subscription.
|
||||
|
||||
For steps on how you can do this, see [step 1 of onboarding your organization](/manuals/admin/organization/setup/onboard.md).
|
||||
|
||||
### Assign roles strategically
|
||||
|
||||
When you invite members to join your Docker organization, you assign them a role.
|
||||
|
||||
Docker's predefined roles offer flexibility for various organizational needs. Assigning roles effectively ensures a balance of accessibility and security.
|
||||
|
||||
- Member: Non-administrative role. Members can view other members that are in the same organization.
|
||||
- Editor: Partial administrative access to the organization. Editors can create, edit, and delete repositories. They can also edit an existing team's access permissions.
|
||||
- Owner: Full organization administrative access. Owners can manage organization repositories, teams, members, settings, and billing.
|
||||
|
||||
For more information, see [Roles and permissions](/manuals/enterprise/security/roles-and-permissions.md).
|
||||
|
||||
#### Enhance with teams
|
||||
|
||||
Teams in Docker provide a structured way to manage member access and they provide an additional level of permissions. They simplify permission management and enable consistent application of policies.
|
||||
|
||||
- Organize users into teams aligned with projects, departments, or functional roles. This approach helps streamline resource allocation and ensures clarity in access control.
|
||||
- Assign permissions at the team level rather than individually. For instance, a development team might have "Read & Write" access to certain repositories, while a QA team has "Read-only" access.
|
||||
- As teams grow or responsibilities shift, you can easily update permissions or add new members, maintaining consistency without reconfiguring individual settings.
|
||||
|
||||
For more information, see [Create and manage a team](/manuals/admin/organization/manage/manage-a-team.md).
|
||||
|
||||
#### Example scenarios
|
||||
|
||||
- Development teams: Assign the member role to developers, granting access to the repositories needed for coding and testing.
|
||||
- Team leads: Assign the editor role to team leads for resource management and repository control within their teams.
|
||||
- Organizational oversight: Restrict the organization owner or company owner roles to a select few trusted individuals responsible for billing and security settings.
|
||||
|
||||
#### Best practices
|
||||
|
||||
- Apply the principle of least privilege. Assign users only the minimum permissions necessary for their roles.
|
||||
- Conduct regular reviews of role assignments to ensure they align with evolving team structures and organizational responsibilities.
|
||||
|
||||
## Onboarding and managing roles and permissions in Docker
|
||||
|
||||
This page guides you through onboarding owners and members, and using tools like SSO and SCIM to future-proof onboarding going forward.
|
||||
|
||||
### Invite owners
|
||||
|
||||
When you create a Docker organization, you automatically become its sole owner. While optional, adding additional owners can significantly ease the process of onboarding and managing your organization by distributing administrative responsibilities. It also ensures continuity and prevents blockers if the primary owner is unavailable.
|
||||
|
||||
For detailed information on owners, see [Roles and permissions](/manuals/enterprise/security/roles-and-permissions.md).
|
||||
|
||||
### Invite members and assign roles
|
||||
|
||||
Members are granted controlled access to resources and enjoy enhanced organizational benefits. When you invite members to join your Docker organization, you immediately assign them a role.
|
||||
|
||||
#### Benefits of inviting members
|
||||
|
||||
- Enhanced visibility: Gain insights into user activity, making it easier to monitor access and enforce security policies.
|
||||
- Streamlined collaboration: Help members collaborate effectively by granting access to shared resources and repositories.
|
||||
- Improved resource management: Organize and track users within your organization, ensuring optimal allocation of resources.
|
||||
- Access to enhanced features: Members benefit from organization-wide perks, such as increased pull limits and access to premium Docker features.
|
||||
- Security control: Apply and enforce security settings at an organizational level, reducing risks associated with unmanaged accounts.
|
||||
|
||||
For detailed information, see [Manage organization members](/manuals/admin/organization/manage/members.md).
|
||||
|
||||
### Future-proof user management
|
||||
|
||||
A robust, future-proof approach to user management combines automated provisioning, centralized authentication, and dynamic access control. Implementing these practices ensures a scalable, secure, and efficient environment.
|
||||
|
||||
#### Secure user authentication with single sign-on (SSO)
|
||||
|
||||
Integrating Docker with your identity provider streamlines user access and enhances security.
|
||||
|
||||
SSO:
|
||||
|
||||
- Simplifies sign in, as users sign in with their organizational credentials.
|
||||
- Reduces password-related vulnerabilities.
|
||||
- Simplifies onboarding as it works seamlessly with SCIM and group mapping for automated provisioning.
|
||||
|
||||
For more information, see the [SSO documentation](/manuals/enterprise/security/single-sign-on/_index.md).
|
||||
|
||||
#### Automate onboarding with SCIM and JIT provisioning
|
||||
|
||||
Streamline user provisioning and role management with [SCIM](/manuals/enterprise/security/provisioning/scim/_index.md) and [Just-in-Time (JIT) provisioning](/manuals/enterprise/security/provisioning/just-in-time.md).
|
||||
|
||||
With SCIM you can:
|
||||
|
||||
- Sync users and roles automatically with your identity provider.
|
||||
- Automate adding, updating, or removing users based on directory changes.
|
||||
|
||||
With JIT provisioning you can:
|
||||
|
||||
- Automatically add users upon first sign in based on [group mapping](#simplify-access-with-group-mapping).
|
||||
- Reduce overhead by eliminating pre-invite steps.
|
||||
|
||||
#### Simplify access with group mapping
|
||||
|
||||
Group mapping automates permissions management by linking identity provider groups to Docker roles and teams.
|
||||
|
||||
It also:
|
||||
|
||||
- Reduces manual errors in role assignments.
|
||||
- Ensures consistent access control policies.
|
||||
- Help you scale permissions as teams grow or change.
|
||||
|
||||
For more information on how it works, see [Group mapping](/manuals/enterprise/security/provisioning/scim/group-mapping.md).
|
||||
|
||||
## Monitoring and insights
|
||||
|
||||
Activity logs and Insights are useful tools for user and access management in Docker. They provide visibility into user actions, team workflows, and organizational trends, helping enhance security, ensure compliance, and boost productivity.
|
||||
|
||||
### Activity logs
|
||||
|
||||
Activity logs track events at the organization and repository levels, offering a clear view of activities like repository changes, team updates, and billing adjustments.
|
||||
|
||||
Activity logs are available for Docker Team or Docker Business plans, with data retained for three months.
|
||||
|
||||
#### Key features
|
||||
|
||||
- Change tracking: View what changed, who made the change, and when.
|
||||
- Comprehensive reporting: Monitor critical events such as repository creation, deletion, privacy changes, and role assignments.
|
||||
|
||||
#### Example scenarios
|
||||
|
||||
- Audit trail for security: A repository’s privacy settings were updated unexpectedly. The activity logs reveal which user made the change and when, helping administrators address potential security risks.
|
||||
- Team collaboration review: Logs show which team members pushed updates to a critical repository, ensuring accountability during a development sprint.
|
||||
- Billing adjustments: Track who added or removed subscription seats to maintain budgetary control and compliance.
|
||||
|
||||
For more information, see [Activity logs](/manuals/admin/activity-logs.md).
|
||||
|
||||
### Insights
|
||||
|
||||
Insights provide data-driven views of Docker usage to improve team productivity and resource allocation.
|
||||
|
||||
#### Key benefits
|
||||
|
||||
- Standardized environments: Ensure consistent configurations and enforce best practices across teams.
|
||||
- Improved visibility: Monitor metrics like Docker Desktop usage, builds, and container activity to understand team workflows and engagement.
|
||||
- Optimized resources: Track license usage and feature adoption to maximize the value of your Docker subscription.
|
||||
|
||||
#### Example scenarios
|
||||
|
||||
- Usage trends: Identify underutilized licenses or resources, allowing reallocation to more active teams.
|
||||
- Build efficiency: Track average build times and success rates to pinpoint bottlenecks in development processes.
|
||||
- Container utilization: Analyze container activity across departments to ensure proper resource distribution and cost efficiency.
|
||||
|
||||
For more information, see [Insights](/manuals/admin/insights.md).
|
||||
|
||||
### Next steps
|
||||
|
||||
Now that you've mastered user and access management in Docker, you can:
|
||||
|
||||
- Review your [activity logs](/manuals/admin/activity-logs.md) regularly to maintain security awareness
|
||||
- Check your [Insights dashboard](/manuals/admin/insights.md) to identify opportunities for optimization
|
||||
- Explore [advanced security features](/manuals/enterprise/security/_index.md) to further enhance your Docker environment
|
||||
- Share best practices with your team to ensure consistent adoption of security policies
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
title: Onboarding and managing roles and permissions in Docker
|
||||
description: Learn how to manage roles, invite members, and implement scalable access control in Docker for secure and efficient collaboration.
|
||||
keywords: sso, scim, jit, invite members, docker hub, docker admin console, onboarding, security
|
||||
weight: 20
|
||||
---
|
||||
|
||||
This page guides you through onboarding owners and members, and using tools like SSO and SCIM to future-proof onboarding going forward.
|
||||
|
||||
## Invite owners
|
||||
|
||||
When you create a Docker organization, you automatically become its sole owner. While optional, adding additional owners can significantly ease the process of onboarding and managing your organization by distributing administrative responsibilities. It also ensures continuity and prevents blockers if the primary owner is unavailable.
|
||||
|
||||
For detailed information on owners, see [Roles and permissions](/manuals/enterprise/security/roles-and-permissions.md).
|
||||
|
||||
## Invite members and assign roles
|
||||
|
||||
Members are granted controlled access to resources and enjoy enhanced organizational benefits. When you invite members to join your Docker organization, you immediately assign them a role.
|
||||
|
||||
### Benefits of inviting members
|
||||
|
||||
- Enhanced visibility: Gain insights into user activity, making it easier to monitor access and enforce security policies.
|
||||
- Streamlined collaboration: Help members collaborate effectively by granting access to shared resources and repositories.
|
||||
- Improved resource management: Organize and track users within your organization, ensuring optimal allocation of resources.
|
||||
- Access to enhanced features: Members benefit from organization-wide perks, such as increased pull limits and access to premium Docker features.
|
||||
- Security control: Apply and enforce security settings at an organizational level, reducing risks associated with unmanaged accounts.
|
||||
|
||||
For detailed information, see [Manage organization members](/manuals/admin/organization/manage/members.md).
|
||||
|
||||
## Future-proof user management
|
||||
|
||||
A robust, future-proof approach to user management combines automated provisioning, centralized authentication, and dynamic access control. Implementing these practices ensures a scalable, secure, and efficient environment.
|
||||
|
||||
### Secure user authentication with single sign-on (SSO)
|
||||
|
||||
Integrating Docker with your identity provider streamlines user access and enhances security.
|
||||
|
||||
SSO:
|
||||
|
||||
- Simplifies sign in, as users sign in with their organizational credentials.
|
||||
- Reduces password-related vulnerabilities.
|
||||
- Simplifies onboarding as it works seamlessly with SCIM and group mapping for automated provisioning.
|
||||
|
||||
For more information, see the [SSO documentation](/manuals/enterprise/security/single-sign-on/_index.md).
|
||||
|
||||
### Automate onboarding with SCIM and JIT provisioning
|
||||
|
||||
Streamline user provisioning and role management with [SCIM](/manuals/enterprise/security/provisioning/scim/_index.md) and [Just-in-Time (JIT) provisioning](/manuals/enterprise/security/provisioning/just-in-time.md).
|
||||
|
||||
With SCIM you can:
|
||||
|
||||
- Sync users and roles automatically with your identity provider.
|
||||
- Automate adding, updating, or removing users based on directory changes.
|
||||
|
||||
With JIT provisioning you can:
|
||||
|
||||
- Automatically add users upon first sign in based on [group mapping](#simplify-access-with-group-mapping).
|
||||
- Reduce overhead by eliminating pre-invite steps.
|
||||
|
||||
### Simplify access with group mapping
|
||||
|
||||
Group mapping automates permissions management by linking identity provider groups to Docker roles and teams.
|
||||
|
||||
It also:
|
||||
|
||||
- Reduces manual errors in role assignments.
|
||||
- Ensures consistent access control policies.
|
||||
- Help you scale permissions as teams grow or change.
|
||||
|
||||
For more information on how it works, see [Group mapping](/manuals/enterprise/security/provisioning/scim/group-mapping.md).
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
title: Setting up roles and permissions in Docker
|
||||
description: A guide to securely managing access and collaboration in Docker through roles and teams.
|
||||
keywords: Docker roles, permissions management, access control, IT administration, team collaboration, least privilege, security, Docker Teams, role-based access
|
||||
weight: 10
|
||||
---
|
||||
|
||||
With the right configurations, you can ensure your developers have easy access to necessary resources while preventing unauthorized access. This page guides you through identifying Docker users so you can allocate subscription seats efficiently within your Docker organization, and assigning roles to align with your organization's structure.
|
||||
|
||||
## Identify your Docker users and accounts
|
||||
|
||||
Before setting up roles and permissions, it's important to have a clear understanding of who in your organization requires Docker access. Focus on gathering a comprehensive view of active users, their roles within projects, and how they interact with Docker resources. This process can be supported by tools like device management software or manual assessments. Encourage all users to update their Docker accounts to use organizational email addresses, ensuring seamless integration with your subscription.
|
||||
|
||||
For steps on how you can do this, see [step 1 of onboarding your organization](/manuals/admin/organization/setup/onboard.md).
|
||||
|
||||
## Assign roles strategically
|
||||
|
||||
When you invite members to join your Docker organization, you assign them a role.
|
||||
|
||||
Docker's predefined roles offer flexibility for various organizational needs. Assigning roles effectively ensures a balance of accessibility and security.
|
||||
|
||||
- Member: Non-administrative role. Members can view other members that are in the same organization.
|
||||
- Editor: Partial administrative access to the organization. Editors can create, edit, and delete repositories. They can also edit an existing team's access permissions.
|
||||
- Owner: Full organization administrative access. Owners can manage organization repositories, teams, members, settings, and billing.
|
||||
|
||||
For more information, see [Roles and permissions](/manuals/enterprise/security/roles-and-permissions.md).
|
||||
|
||||
### Enhance with teams
|
||||
|
||||
Teams in Docker provide a structured way to manage member access and they provide an additional level of permissions. They simplify permission management and enable consistent application of policies.
|
||||
|
||||
- Organize users into teams aligned with projects, departments, or functional roles. This approach helps streamline resource allocation and ensures clarity in access control.
|
||||
- Assign permissions at the team level rather than individually. For instance, a development team might have "Read & Write" access to certain repositories, while a QA team has "Read-only" access.
|
||||
- As teams grow or responsibilities shift, you can easily update permissions or add new members, maintaining consistency without reconfiguring individual settings.
|
||||
|
||||
For more information, see [Create and manage a team](/manuals/admin/organization/manage/manage-a-team.md).
|
||||
|
||||
### Example scenarios
|
||||
|
||||
- Development teams: Assign the member role to developers, granting access to the repositories needed for coding and testing.
|
||||
- Team leads: Assign the editor role to team leads for resource management and repository control within their teams.
|
||||
- Organizational oversight: Restrict the organization owner or company owner roles to a select few trusted individuals responsible for billing and security settings.
|
||||
|
||||
### Best practices
|
||||
|
||||
- Apply the principle of least privilege. Assign users only the minimum permissions necessary for their roles.
|
||||
- Conduct regular reviews of role assignments to ensure they align with evolving team structures and organizational responsibilities.
|
||||
@@ -5,7 +5,7 @@ keywords: AI, Docker, Model Runner, MCP Toolkit, AI agents, application developm
|
||||
summary: |
|
||||
Learn how to create AI agent applications using Docker Model Runner, and MCP Toolkit.
|
||||
params:
|
||||
tags: [AI]
|
||||
tags: [ai]
|
||||
time: 30 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
title: Angular language-specific guide
|
||||
linkTitle: Angular
|
||||
description: Containerize and develop Angular apps using Docker
|
||||
keywords: getting started, angular, docker, language, Dockerfile
|
||||
summary: |
|
||||
This guide explains how to containerize Angular applications using Docker.
|
||||
toc_min: 1
|
||||
toc_max: 2
|
||||
aliases:
|
||||
- /guides/angular/configure-github-actions/
|
||||
- /guides/angular/deploy/
|
||||
languages: [js]
|
||||
params:
|
||||
time: 20 minutes
|
||||
|
||||
---
|
||||
|
||||
The Angular language-specific guide shows you how to containerize an Angular application using Docker, following best practices for creating efficient, production-ready containers.
|
||||
|
||||
[Angular](https://angular.dev/) is a robust and widely adopted framework for building dynamic, enterprise-grade web applications. However, managing dependencies, environments, and deployments can become complex as applications scale. Docker streamlines these challenges by offering a consistent, isolated environment for development and production.
|
||||
|
||||
>
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker extends its sincere gratitude to [Kristiyan Velkov](https://www.linkedin.com/in/kristiyan-velkov-763130b3/) for authoring this guide. As a Docker Captain and experienced Front-end engineer, his expertise in Docker, DevOps, and modern web development has made this resource essential for the community, helping developers navigate and optimize their Docker workflows.
|
||||
|
||||
---
|
||||
|
||||
## What will you learn?
|
||||
|
||||
In this guide, you will learn how to:
|
||||
|
||||
- Containerize and run an Angular application using Docker.
|
||||
- Set up a local development environment for Angular inside a container.
|
||||
- Run tests for your Angular application within a Docker container.
|
||||
You'll start by containerizing an existing Angular application.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have a working knowledge of:
|
||||
|
||||
- Basic understanding of [TypeScript](https://www.typescriptlang.org/) and [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript).
|
||||
- Familiarity with [Node.js](https://nodejs.org/en) and [npm](https://docs.npmjs.com/about-npm) for managing dependencies and running scripts.
|
||||
- Familiarity with [Angular](https://angular.io/) fundamentals.
|
||||
- Understanding of core Docker concepts such as images, containers, and Dockerfiles. If you're new to Docker, start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
Once you've completed the Angular getting started modules, you’ll be fully prepared to containerize your own Angular application using the detailed examples and best practices outlined in this guide.
|
||||
@@ -1,178 +0,0 @@
|
||||
---
|
||||
title: Use containers for Angular development
|
||||
linkTitle: Develop your app
|
||||
weight: 30
|
||||
keywords: angular, development, node
|
||||
description: Learn how to develop your Angular application locally using containers.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Containerize Angular application](containerize.md).
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll learn how to set up both production and development environments for your containerized Angular application using Docker Compose. This setup allows you to serve a static production build via Nginx and to develop efficiently inside containers using a live-reloading dev server with Compose Watch.
|
||||
|
||||
You’ll learn how to:
|
||||
- Configure separate containers for production and development
|
||||
- Enable automatic file syncing using Compose Watch in development
|
||||
- Debug and live-preview your changes in real-time without manual rebuilds
|
||||
|
||||
---
|
||||
|
||||
## Automatically update services (development mode)
|
||||
|
||||
Use Compose Watch to automatically sync source file changes into your containerized development environment. This provides a seamless, efficient development experience without restarting or rebuilding containers manually.
|
||||
|
||||
## Step 1: Create a development Dockerfile
|
||||
|
||||
Create a file named `Dockerfile.dev` in your project root with the following content:
|
||||
|
||||
```dockerfile
|
||||
# =========================================
|
||||
# Stage 1: Development - Angular Application
|
||||
# =========================================
|
||||
|
||||
# Define the Node.js version to use (Alpine for a small footprint)
|
||||
ARG NODE_VERSION=24.12.0-alpine
|
||||
|
||||
# Set the base image for development
|
||||
FROM node:${NODE_VERSION} AS dev
|
||||
|
||||
# Set environment variable to indicate development mode
|
||||
ENV NODE_ENV=development
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only the dependency files first to optimize Docker caching
|
||||
COPY package.json package-lock.json* ./
|
||||
|
||||
# Install dependencies using npm with caching to speed up subsequent builds
|
||||
RUN --mount=type=cache,target=/root/.npm npm install
|
||||
|
||||
# Copy all application source files into the container
|
||||
COPY . .
|
||||
|
||||
# Expose the port Angular uses for the dev server (default is 4200)
|
||||
EXPOSE 4200
|
||||
|
||||
# Start the Angular dev server and bind it to all network interfaces
|
||||
CMD ["npm", "start", "--", "--host=0.0.0.0"]
|
||||
|
||||
```
|
||||
|
||||
This file sets up a lightweight development environment for your Angular application using the dev server.
|
||||
|
||||
|
||||
### Step 2: Update your `compose.yaml` file
|
||||
|
||||
Open your `compose.yaml` file and define two services: one for production (`angular-prod`) and one for development (`angular-dev`).
|
||||
|
||||
Here’s an example configuration for an Angular application:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
angular-prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: docker-angular-sample
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
angular-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- "4200:4200"
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: .
|
||||
target: /app
|
||||
```
|
||||
- The `angular-prod` service builds and serves your static production app using Nginx.
|
||||
- The `angular-dev` service runs your Angular development server with live reload and hot module replacement.
|
||||
- `watch` triggers file sync with Compose Watch.
|
||||
|
||||
> [!NOTE]
|
||||
> For more details, see the official guide: [Use Compose Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
After completing the previous steps, your project directory should now contain the following files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── Dockerfile.dev
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ └── nginx.conf
|
||||
```
|
||||
|
||||
### Step 4: Start Compose Watch
|
||||
|
||||
Run the following command from the project root to start the container in watch mode
|
||||
|
||||
```console
|
||||
$ docker compose watch angular-dev
|
||||
```
|
||||
|
||||
### Step 5: Test Compose Watch with Angular
|
||||
|
||||
To verify that Compose Watch is working correctly:
|
||||
|
||||
1. Open the `src/app/app.component.html` file in your text editor.
|
||||
|
||||
2. Locate the following line:
|
||||
|
||||
```html
|
||||
<h1>Docker Angular Sample Application</h1>
|
||||
```
|
||||
|
||||
3. Change it to:
|
||||
|
||||
```html
|
||||
<h1>Hello from Docker Compose Watch</h1>
|
||||
```
|
||||
|
||||
4. Save the file.
|
||||
|
||||
5. Open your browser at [http://localhost:4200](http://localhost:4200).
|
||||
|
||||
You should see the updated text appear instantly, without needing to rebuild the container manually. This confirms that file watching and automatic synchronization are working as expected.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you set up a complete development and production workflow for your Angular application using Docker and Docker Compose.
|
||||
|
||||
Here’s what you accomplished:
|
||||
- Created a `Dockerfile.dev` to streamline local development with hot reloading
|
||||
- Defined separate `angular-dev` and `angular-prod` services in your `compose.yaml` file
|
||||
- Enabled real-time file syncing using Compose Watch for a smoother development experience
|
||||
- Verified that live updates work seamlessly by modifying and previewing a component
|
||||
|
||||
With this setup, you're now equipped to build, run, and iterate on your Angular app entirely within containers—efficiently and consistently across environments.
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
|
||||
Deepen your knowledge and improve your containerized development workflow with these guides:
|
||||
|
||||
- [Using Compose Watch](/manuals/compose/how-tos/file-watch.md) – Automatically sync source changes during development
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md) – Create efficient, production-ready Docker images
|
||||
- [Dockerfile best practices](/build/building/best-practices/) – Write clean, secure, and optimized Dockerfiles.
|
||||
- [Compose file reference](/compose/compose-file/) – Learn the full syntax and options available for configuring services in `compose.yaml`.
|
||||
- [Docker volumes](/storage/volumes/) – Persist and manage data between container runs
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how to run unit tests for your Angular application inside Docker containers. This ensures consistent testing across all environments and removes dependencies on local machine setup.
|
||||
@@ -1,14 +1,58 @@
|
||||
---
|
||||
title: Containerize an Angular Application
|
||||
linkTitle: Containerize
|
||||
weight: 10
|
||||
keywords: angular, node, image, initialize, build
|
||||
description: Learn how to containerize an Angular application with Docker by creating an optimized, production-ready image using best practices for performance, security, and scalability.
|
||||
title: Angular language-specific guide
|
||||
linkTitle: Angular
|
||||
description: Containerize and develop Angular apps using Docker
|
||||
keywords: getting started, angular, docker, language, Dockerfile
|
||||
summary: |
|
||||
This guide explains how to containerize Angular applications using Docker.
|
||||
aliases:
|
||||
- /guides/angular/configure-github-actions/
|
||||
- /guides/angular/containerize/
|
||||
- /guides/angular/deploy/
|
||||
- /guides/angular/develop/
|
||||
- /guides/angular/run-tests/
|
||||
params:
|
||||
tags: [languages]
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
The Angular language-specific guide shows you how to containerize an Angular application using Docker, following best practices for creating efficient, production-ready containers.
|
||||
|
||||
[Angular](https://angular.dev/) is a robust and widely adopted framework for building dynamic, enterprise-grade web applications. However, managing dependencies, environments, and deployments can become complex as applications scale. Docker streamlines these challenges by offering a consistent, isolated environment for development and production.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker extends its sincere gratitude to [Kristiyan Velkov](https://www.linkedin.com/in/kristiyan-velkov-763130b3/) for authoring this guide. As a Docker Captain and experienced Front-end engineer, his expertise in Docker, DevOps, and modern web development has made this resource essential for the community, helping developers navigate and optimize their Docker workflows.
|
||||
|
||||
---
|
||||
|
||||
## What will you learn?
|
||||
|
||||
In this guide, you will learn how to:
|
||||
|
||||
- Containerize and run an Angular application using Docker.
|
||||
- Set up a local development environment for Angular inside a container.
|
||||
- Run tests for your Angular application within a Docker container.
|
||||
|
||||
You'll start by containerizing an existing Angular application and work your way up to production-level deployments.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have a working knowledge of:
|
||||
|
||||
- Basic understanding of [TypeScript](https://www.typescriptlang.org/) and [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript).
|
||||
- Familiarity with [Node.js](https://nodejs.org/en) and [npm](https://docs.npmjs.com/about-npm) for managing dependencies and running scripts.
|
||||
- Familiarity with [Angular](https://angular.io/) fundamentals.
|
||||
- Understanding of core Docker concepts such as images, containers, and Dockerfiles. If you're new to Docker, start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
Once you've completed the Angular getting started modules, you’ll be fully prepared to containerize your own Angular application using the detailed examples and best practices outlined in this guide.
|
||||
|
||||
## Containerize an Angular Application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before you begin, make sure the following tools are installed and available on your system:
|
||||
|
||||
- You have installed the latest version of [Docker Desktop](/get-started/get-docker.md).
|
||||
@@ -19,21 +63,21 @@ Before you begin, make sure the following tools are installed and available on y
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
### Overview
|
||||
|
||||
This guide walks you through the complete process of containerizing an Angular application with Docker. You’ll learn how to create a production-ready Docker image using best practices that improve performance, security, scalability, and deployment efficiency.
|
||||
|
||||
By the end of this guide, you will:
|
||||
|
||||
- Containerize an Angular application using Docker.
|
||||
- Create and optimize a Dockerfile for production builds.
|
||||
- Create and optimize a Dockerfile for production builds.
|
||||
- Use multi-stage builds to minimize image size.
|
||||
- Serve the application efficiently with a custom Nginx configuration.
|
||||
- Build secure and maintainable Docker images by following best practices.
|
||||
|
||||
---
|
||||
|
||||
## Get the sample application
|
||||
### Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, navigate to the directory where you want to work, and run the following command
|
||||
to clone the git repository:
|
||||
@@ -41,9 +85,10 @@ to clone the git repository:
|
||||
```console
|
||||
$ git clone https://github.com/kristiyan-velkov/docker-angular-sample
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Build the Docker image
|
||||
### Build the Docker image
|
||||
|
||||
Angular is a front-end framework that compiles into static assets, so the Dockerfile uses a multi-stage build: one stage compiles the app with Node.js, and a second minimal stage serves the static output with Nginx.
|
||||
|
||||
@@ -51,7 +96,7 @@ Angular is a front-end framework that compiles into static assets, so the Docker
|
||||
>
|
||||
> [Gordon](/ai/gordon/), Docker's AI assistant, can generate Docker assets for your project. Ask Gordon to create a Dockerfile, Compose file, and `.dockerignore` tailored to your application.
|
||||
|
||||
### Step 1: Create the Dockerfile
|
||||
#### Step 1: Create the Dockerfile
|
||||
|
||||
Before creating a Dockerfile, you need to choose a base image. You can either use the [Node.js Official Image](https://hub.docker.com/_/node) or a Docker Hardened Image (DHI) from the [Hardened Image catalog](https://hub.docker.com/hardened-images/catalog).
|
||||
|
||||
@@ -67,6 +112,7 @@ Choosing DHI offers the advantage of a production-ready image that is lightweigh
|
||||
Docker Hardened Images (DHIs) are available for Node.js in the [Docker Hardened Images catalog](https://hub.docker.com/hardened-images/catalog/dhi/node). Docker Hardened Images are freely available to everyone with no subscription required. You can pull and use them like any other Docker image after signing in to the DHI registry. For more information, see the [DHI quickstart](/dhi/get-started/) guide.
|
||||
|
||||
1. Sign in to the DHI registry:
|
||||
|
||||
```console
|
||||
$ docker login dhi.io
|
||||
```
|
||||
@@ -99,7 +145,7 @@ RUN --mount=type=cache,target=/root/.npm npm ci
|
||||
COPY . .
|
||||
|
||||
# Build the Angular application
|
||||
RUN npm run build
|
||||
RUN npm run build
|
||||
|
||||
# =========================================
|
||||
# Stage 2: Prepare Nginx to Serve Static Files
|
||||
@@ -117,7 +163,7 @@ COPY --chown=nginx:nginx --from=builder /app/dist/*/browser /usr/share/nginx/htm
|
||||
USER nginx
|
||||
|
||||
# Expose port 8080 to allow HTTP traffic
|
||||
# Note: The default Nginx container now listens on port 8080 instead of 80
|
||||
# Note: The default Nginx container now listens on port 8080 instead of 80
|
||||
EXPOSE 8080
|
||||
|
||||
# Start Nginx directly with custom config
|
||||
@@ -153,7 +199,7 @@ RUN --mount=type=cache,target=/root/.npm npm ci
|
||||
COPY . .
|
||||
|
||||
# Build the Angular application
|
||||
RUN npm run build
|
||||
RUN npm run build
|
||||
|
||||
# =========================================
|
||||
# Stage 2: Prepare Nginx to Serve Static Files
|
||||
@@ -171,7 +217,7 @@ COPY --chown=nginx:nginx --from=builder /app/dist/*/browser /usr/share/nginx/htm
|
||||
USER nginx
|
||||
|
||||
# Expose port 8080 to allow HTTP traffic
|
||||
# Note: The default Nginx container now listens on port 8080 instead of 80
|
||||
# Note: The default Nginx container now listens on port 8080 instead of 80
|
||||
EXPOSE 8080
|
||||
|
||||
# Start Nginx directly with custom config
|
||||
@@ -182,14 +228,15 @@ CMD ["-g", "daemon off;"]
|
||||
> [!NOTE]
|
||||
> We are using nginx-unprivileged instead of the standard Nginx image to follow security best practices.
|
||||
> Running as a non-root user in the final image:
|
||||
>- Reduces the attack surface
|
||||
>- Aligns with Docker’s recommendations for container hardening
|
||||
>- Helps comply with stricter security policies in production environments
|
||||
>
|
||||
> - Reduces the attack surface
|
||||
> - Aligns with Docker’s recommendations for container hardening
|
||||
> - Helps comply with stricter security policies in production environments
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Step 2: Create the compose.yaml file
|
||||
#### Step 2: Create the compose.yaml file
|
||||
|
||||
Create a file named `compose.yaml` with the following contents:
|
||||
|
||||
@@ -202,15 +249,16 @@ services:
|
||||
- 8080:8080
|
||||
```
|
||||
|
||||
### Step 3: Create the .dockerignore file
|
||||
#### Step 3: Create the .dockerignore file
|
||||
|
||||
The `.dockerignore` file tells Docker which files and folders to exclude when building the image.
|
||||
|
||||
> [!NOTE]
|
||||
>This helps:
|
||||
>- Reduce image size
|
||||
>- Speed up the build process
|
||||
>- Prevent sensitive or unnecessary files (like `.env`, `.git`, or `node_modules`) from being added to the final image.
|
||||
> This helps:
|
||||
>
|
||||
> - Reduce image size
|
||||
> - Speed up the build process
|
||||
> - Prevent sensitive or unnecessary files (like `.env`, `.git`, or `node_modules`) from being added to the final image.
|
||||
>
|
||||
> To learn more, visit the [.dockerignore reference](/reference/dockerfile.md#dockerignore-file).
|
||||
|
||||
@@ -280,7 +328,7 @@ docker-compose*.yml
|
||||
*.tmp
|
||||
```
|
||||
|
||||
### Step 4: Create the `nginx.conf` file
|
||||
#### Step 4: Create the `nginx.conf` file
|
||||
|
||||
To serve your Angular application efficiently inside the container, you’ll configure Nginx with a custom setup. This configuration is optimized for performance, browser caching, gzip compression, and support for client-side routing.
|
||||
|
||||
@@ -289,7 +337,6 @@ Create a file named `nginx.conf` in the root of your project directory, and add
|
||||
> [!NOTE]
|
||||
> To learn more about configuring Nginx, see the [official Nginx documentation](https://nginx.org/en/docs/).
|
||||
|
||||
|
||||
```nginx
|
||||
worker_processes auto;
|
||||
|
||||
@@ -368,7 +415,7 @@ http {
|
||||
}
|
||||
```
|
||||
|
||||
### Step 5: Build the Angular application image
|
||||
#### Step 5: Build the Angular application image
|
||||
|
||||
With your custom configuration in place, you're now ready to build the Docker image for your Angular application.
|
||||
|
||||
@@ -399,12 +446,12 @@ $ docker build --tag docker-angular-sample .
|
||||
```
|
||||
|
||||
What this command does:
|
||||
|
||||
- Uses the Dockerfile in the current directory (.)
|
||||
- Packages the application and its dependencies into a Docker image
|
||||
- Tags the image as docker-angular-sample so you can reference it later
|
||||
|
||||
|
||||
### Step 6: View local images
|
||||
#### Step 6: View local images
|
||||
|
||||
After building your Docker image, you can check which images are available on your local machine using either the Docker CLI or [Docker Desktop](/manuals/desktop/use-desktop/images.md). Since you're already working in the terminal, let's use the Docker CLI.
|
||||
|
||||
@@ -429,15 +476,14 @@ This output provides key details about your images:
|
||||
- **Created** – The timestamp indicating when the image was built.
|
||||
- **Size** – The total disk space used by the image.
|
||||
|
||||
If the build was successful, you should see `docker-angular-sample` image listed.
|
||||
If the build was successful, you should see `docker-angular-sample` image listed.
|
||||
|
||||
---
|
||||
|
||||
## Run the containerized application
|
||||
### Run the containerized application
|
||||
|
||||
In the previous step, you created a Dockerfile for your Angular application and built a Docker image using the docker build command. Now it’s time to run that image in a container and verify that your application works as expected.
|
||||
|
||||
|
||||
Inside the `docker-angular-sample` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
@@ -449,7 +495,7 @@ Open a browser and view the application at [http://localhost:8080](http://localh
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
### Run the application in the background
|
||||
#### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `docker-angular-sample` directory, run the following command
|
||||
@@ -461,7 +507,6 @@ $ docker compose up --build -d
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see your Angular application running in the browser.
|
||||
|
||||
|
||||
To confirm that the container is running, use `docker ps` command:
|
||||
|
||||
```console
|
||||
@@ -477,53 +522,284 @@ CONTAINER ID IMAGE COMMAND CREATED
|
||||
eb13026806d1 docker-angular-sample-server "nginx -c /etc/nginx…" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp docker-angular-sample-server-1
|
||||
```
|
||||
|
||||
|
||||
To stop the application, run:
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
|
||||
> [!NOTE]
|
||||
> For more information about Compose commands, see the [Compose CLI
|
||||
> reference](/reference/cli/docker/compose/).
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
## Use containers for Angular development
|
||||
|
||||
In this guide, you learned how to containerize, build, and run an Angular application using Docker. By following best practices, you created a secure, optimized, and production-ready setup.
|
||||
### Prerequisites
|
||||
|
||||
Complete [Containerize Angular application](./).
|
||||
|
||||
---
|
||||
|
||||
### Overview
|
||||
|
||||
In this section, you'll learn how to set up both production and development environments for your containerized Angular application using Docker Compose. This setup allows you to serve a static production build via Nginx and to develop efficiently inside containers using a live-reloading dev server with Compose Watch.
|
||||
|
||||
You’ll learn how to:
|
||||
|
||||
- Configure separate containers for production and development
|
||||
- Enable automatic file syncing using Compose Watch in development
|
||||
- Debug and live-preview your changes in real-time without manual rebuilds
|
||||
|
||||
---
|
||||
|
||||
### Automatically update services (development mode)
|
||||
|
||||
Use Compose Watch to automatically sync source file changes into your containerized development environment. This provides a seamless, efficient development experience without restarting or rebuilding containers manually.
|
||||
|
||||
### Step 1: Create a development Dockerfile
|
||||
|
||||
Create a file named `Dockerfile.dev` in your project root with the following content:
|
||||
|
||||
```dockerfile
|
||||
# =========================================
|
||||
# Stage 1: Development - Angular Application
|
||||
# =========================================
|
||||
|
||||
# Define the Node.js version to use (Alpine for a small footprint)
|
||||
ARG NODE_VERSION=24.12.0-alpine
|
||||
|
||||
# Set the base image for development
|
||||
FROM node:${NODE_VERSION} AS dev
|
||||
|
||||
# Set environment variable to indicate development mode
|
||||
ENV NODE_ENV=development
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only the dependency files first to optimize Docker caching
|
||||
COPY package.json package-lock.json* ./
|
||||
|
||||
# Install dependencies using npm with caching to speed up subsequent builds
|
||||
RUN --mount=type=cache,target=/root/.npm npm install
|
||||
|
||||
# Copy all application source files into the container
|
||||
COPY . .
|
||||
|
||||
# Expose the port Angular uses for the dev server (default is 4200)
|
||||
EXPOSE 4200
|
||||
|
||||
# Start the Angular dev server and bind it to all network interfaces
|
||||
CMD ["npm", "start", "--", "--host=0.0.0.0"]
|
||||
|
||||
```
|
||||
|
||||
This file sets up a lightweight development environment for your Angular application using the dev server.
|
||||
|
||||
#### Step 2: Update your `compose.yaml` file
|
||||
|
||||
Open your `compose.yaml` file and define two services: one for production (`angular-prod`) and one for development (`angular-dev`).
|
||||
|
||||
Here’s an example configuration for an Angular application:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
angular-prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: docker-angular-sample
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
angular-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- "4200:4200"
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: .
|
||||
target: /app
|
||||
```
|
||||
|
||||
- The `angular-prod` service builds and serves your static production app using Nginx.
|
||||
- The `angular-dev` service runs your Angular development server with live reload and hot module replacement.
|
||||
- `watch` triggers file sync with Compose Watch.
|
||||
|
||||
> [!NOTE]
|
||||
> For more details, see the official guide: [Use Compose Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
After completing the previous steps, your project directory should now contain the following files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── Dockerfile.dev
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ └── nginx.conf
|
||||
```
|
||||
|
||||
#### Step 4: Start Compose Watch
|
||||
|
||||
Run the following command from the project root to start the container in watch mode
|
||||
|
||||
```console
|
||||
$ docker compose watch angular-dev
|
||||
```
|
||||
|
||||
#### Step 5: Test Compose Watch with Angular
|
||||
|
||||
To verify that Compose Watch is working correctly:
|
||||
|
||||
1. Open the `src/app/app.component.html` file in your text editor.
|
||||
|
||||
2. Locate the following line:
|
||||
|
||||
```html
|
||||
<h1>Docker Angular Sample Application</h1>
|
||||
```
|
||||
|
||||
3. Change it to:
|
||||
|
||||
```html
|
||||
<h1>Hello from Docker Compose Watch</h1>
|
||||
```
|
||||
|
||||
4. Save the file.
|
||||
|
||||
5. Open your browser at [http://localhost:4200](http://localhost:4200).
|
||||
|
||||
You should see the updated text appear instantly, without needing to rebuild the container manually. This confirms that file watching and automatic synchronization are working as expected.
|
||||
|
||||
---
|
||||
|
||||
## Run Angular tests in a container
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Complete all the previous sections of this guide, starting with [Containerize Angular application](./).
|
||||
|
||||
### Overview
|
||||
|
||||
Testing is a critical part of the development process. In this section, you'll learn how to:
|
||||
|
||||
- Run Jasmine unit tests using the Angular CLI inside a Docker container.
|
||||
- Use Docker Compose to isolate your test environment.
|
||||
- Ensure consistency between local and container-based testing.
|
||||
|
||||
The `docker-angular-sample` project comes pre-configured with Jasmine, so you can get started quickly without extra setup.
|
||||
|
||||
---
|
||||
|
||||
### Run tests during development
|
||||
|
||||
The `docker-angular-sample` application includes a sample test file at the following location:
|
||||
|
||||
```console
|
||||
$ src/app/app.component.spec.ts
|
||||
```
|
||||
|
||||
This test uses Jasmine to validate the AppComponent logic.
|
||||
|
||||
#### Step 1: Update compose.yaml
|
||||
|
||||
Add a new service named `angular-test` to your `compose.yaml` file. This service allows you to run your test suite in an isolated, containerized environment.
|
||||
|
||||
```yaml {hl_lines="22-26",linenos=true}
|
||||
services:
|
||||
angular-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- "5173:5173"
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: .
|
||||
target: /app
|
||||
|
||||
angular-prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: docker-angular-sample
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
angular-test:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
command: ["npm", "run", "test"]
|
||||
```
|
||||
|
||||
The angular-test service reuses the same `Dockerfile.dev` used for [development](#use-containers-for-angular-development) and overrides the default command to run tests with `npm run test`. This setup ensures a consistent test environment that matches your local development configuration.
|
||||
|
||||
After completing the previous steps, your project directory should contain the following files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── Dockerfile.dev
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ └── nginx.conf
|
||||
```
|
||||
|
||||
#### Step 2: Run the tests
|
||||
|
||||
To execute your test suite inside the container, run the following command from your project root:
|
||||
|
||||
```console
|
||||
$ docker compose run --rm angular-test
|
||||
```
|
||||
|
||||
This command will:
|
||||
|
||||
- Start the `angular-test` service defined in your `compose.yaml` file.
|
||||
- Execute the `npm run test` script using the same environment as development.
|
||||
- Automatically removes the container after tests complete, using the [`docker compose run --rm`](/reference/cli/docker/compose/run/) command.
|
||||
|
||||
You should see output similar to the following:
|
||||
|
||||
```shell
|
||||
Test Suites: 1 passed, 1 total
|
||||
Tests: 3 passed, 3 total
|
||||
Snapshots: 0 total
|
||||
Time: 1.529 s
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For more information about Compose commands, see the [Compose CLI
|
||||
> reference](/reference/cli/docker/compose/).
|
||||
|
||||
---
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you learned how to run unit tests for your Angular application inside a Docker container using Jasmine and Docker Compose.
|
||||
|
||||
What you accomplished:
|
||||
- Created a multi-stage `Dockerfile` that compiles the Angular application and serves the static files using Nginx.
|
||||
- Created a `.dockerignore` file to exclude unnecessary files and keep the image clean and efficient.
|
||||
- Built your Docker image using `docker build`.
|
||||
- Ran the container using `docker compose up`, both in the foreground and in detached mode.
|
||||
- Verified that the app was running by visiting [http://localhost:8080](http://localhost:8080).
|
||||
- Learned how to stop the containerized application using `docker compose down`.
|
||||
|
||||
You now have a fully containerized Angular application, running in a Docker container, and ready for deployment across any environment with confidence and consistency.
|
||||
- Created a `angular-test` service in `compose.yaml` to isolate test execution.
|
||||
- Reused the development `Dockerfile.dev` to ensure consistency between dev and test environments.
|
||||
- Ran tests inside the container using `docker compose run --rm angular-test`.
|
||||
- Ensured reliable, repeatable testing across environments without depending on your local machine setup.
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
### Related resources
|
||||
|
||||
Explore official references and best practices to sharpen your Docker workflow:
|
||||
|
||||
- [Multi-stage builds](/build/building/multi-stage/) – Learn how to separate build and runtime stages.
|
||||
- [Best practices for writing Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Write efficient, maintainable, and secure Dockerfiles.
|
||||
- [Build context in Docker](/build/concepts/context/) – Learn how context affects image builds.
|
||||
- [`docker build` CLI reference](/reference/cli/docker/image/build/) – Build Docker images from a Dockerfile.
|
||||
- [`docker images` CLI reference](/reference/cli/docker/image/ls/) – Manage and inspect local Docker images.
|
||||
- [`docker compose up` CLI reference](/reference/cli/docker/compose/up/) – Start and run multi-container applications.
|
||||
- [`docker compose down` CLI reference](/reference/cli/docker/compose/down/) – Stop and remove containers, networks, and volumes.
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
With your Angular application now containerized, you're ready to move on to the next step.
|
||||
|
||||
In the next section, you'll learn how to develop your application using Docker containers, enabling a consistent, isolated, and reproducible development environment across any machine.
|
||||
Explore official references and best practices to sharpen your Docker testing workflow:
|
||||
|
||||
- [Dockerfile reference](/reference/dockerfile/) – Understand all Dockerfile instructions and syntax.
|
||||
- [Best practices for writing Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Write efficient, maintainable, and secure Dockerfiles.
|
||||
- [Compose file reference](/compose/compose-file/) – Learn the full syntax and options available for configuring services in `compose.yaml`.
|
||||
- [`docker compose run` CLI reference](/reference/cli/docker/compose/run/) – Run one-off commands in a service container.
|
||||
@@ -1,134 +0,0 @@
|
||||
---
|
||||
title: Run Angular tests in a container
|
||||
linkTitle: Run your tests
|
||||
weight: 40
|
||||
keywords: angular, test, jasmine
|
||||
description: Learn how to run your Angular tests in a container.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete all the previous sections of this guide, starting with [Containerize Angular application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
Testing is a critical part of the development process. In this section, you'll learn how to:
|
||||
|
||||
- Run Jasmine unit tests using the Angular CLI inside a Docker container.
|
||||
- Use Docker Compose to isolate your test environment.
|
||||
- Ensure consistency between local and container-based testing.
|
||||
|
||||
|
||||
The `docker-angular-sample` project comes pre-configured with Jasmine, so you can get started quickly without extra setup.
|
||||
|
||||
---
|
||||
|
||||
## Run tests during development
|
||||
|
||||
The `docker-angular-sample` application includes a sample test file at the following location:
|
||||
|
||||
```console
|
||||
$ src/app/app.component.spec.ts
|
||||
```
|
||||
|
||||
This test uses Jasmine to validate the AppComponent logic.
|
||||
|
||||
### Step 1: Update compose.yaml
|
||||
|
||||
Add a new service named `angular-test` to your `compose.yaml` file. This service allows you to run your test suite in an isolated, containerized environment.
|
||||
|
||||
```yaml {hl_lines="22-26",linenos=true}
|
||||
services:
|
||||
angular-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- "5173:5173"
|
||||
develop:
|
||||
watch:
|
||||
- action: sync
|
||||
path: .
|
||||
target: /app
|
||||
|
||||
angular-prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: docker-angular-sample
|
||||
ports:
|
||||
- "8080:8080"
|
||||
|
||||
angular-test:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
command: ["npm", "run", "test"]
|
||||
|
||||
```
|
||||
|
||||
The angular-test service reuses the same `Dockerfile.dev` used for [development](develop.md) and overrides the default command to run tests with `npm run test`. This setup ensures a consistent test environment that matches your local development configuration.
|
||||
|
||||
|
||||
After completing the previous steps, your project directory should contain the following files:
|
||||
|
||||
```text
|
||||
├── docker-angular-sample/
|
||||
│ ├── Dockerfile
|
||||
│ ├── Dockerfile.dev
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ └── nginx.conf
|
||||
```
|
||||
|
||||
### Step 2: Run the tests
|
||||
|
||||
To execute your test suite inside the container, run the following command from your project root:
|
||||
|
||||
```console
|
||||
$ docker compose run --rm angular-test
|
||||
```
|
||||
|
||||
This command will:
|
||||
- Start the `angular-test` service defined in your `compose.yaml` file.
|
||||
- Execute the `npm run test` script using the same environment as development.
|
||||
- Automatically removes the container after tests complete, using the [`docker compose run --rm`](/reference/cli/docker/compose/run/) command.
|
||||
|
||||
You should see output similar to the following:
|
||||
|
||||
```shell
|
||||
Test Suites: 1 passed, 1 total
|
||||
Tests: 3 passed, 3 total
|
||||
Snapshots: 0 total
|
||||
Time: 1.529 s
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> For more information about Compose commands, see the [Compose CLI
|
||||
> reference](/reference/cli/docker/compose/).
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to run unit tests for your Angular application inside a Docker container using Jasmine and Docker Compose.
|
||||
|
||||
What you accomplished:
|
||||
- Created a `angular-test` service in `compose.yaml` to isolate test execution.
|
||||
- Reused the development `Dockerfile.dev` to ensure consistency between dev and test environments.
|
||||
- Ran tests inside the container using `docker compose run --rm angular-test`.
|
||||
- Ensured reliable, repeatable testing across environments without depending on your local machine setup.
|
||||
|
||||
---
|
||||
|
||||
## Related resources
|
||||
|
||||
Explore official references and best practices to sharpen your Docker testing workflow:
|
||||
|
||||
- [Dockerfile reference](/reference/dockerfile/) – Understand all Dockerfile instructions and syntax.
|
||||
- [Best practices for writing Dockerfiles](/develop/develop-images/dockerfile_best-practices/) – Write efficient, maintainable, and secure Dockerfiles.
|
||||
- [Compose file reference](/compose/compose-file/) – Learn the full syntax and options available for configuring services in `compose.yaml`.
|
||||
- [`docker compose run` CLI reference](/reference/cli/docker/compose/run/) – Run one-off commands in a service container.
|
||||
---
|
||||
|
||||
@@ -5,7 +5,7 @@ summary: |
|
||||
Learn how to automate Docker image build and push using Azure Pipelines.
|
||||
keywords: azure pipelines, azure devops, ci/cd, docker hub, build and push, automation
|
||||
params:
|
||||
tags: [devops]
|
||||
tags: [cicd]
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
@@ -308,5 +308,5 @@ With this Azure Pipelines CI setup, you get:
|
||||
|
||||
- [Azure Pipelines Documentation](https://learn.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops): Comprehensive guide to configuring and managing CI/CD pipelines in Azure DevOps.
|
||||
- [Docker Task for Azure Pipelines](https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/build/docker): Detailed reference for using the Docker task in Azure Pipelines to build and push images.
|
||||
- [Docker Buildx Bake](/manuals/build/bake/_index.md): Explore Docker's advanced build tool for complex, multi-stage, and multi-platform build setups. See also the [Mastering Buildx Bake Guide](/guides/bake/index.md) for practical examples and best practices.
|
||||
- [Docker Buildx Bake](/manuals/build/bake/_index.md): Explore Docker's advanced build tool for complex, multi-stage, and multi-platform build setups. See also the [Mastering Buildx Bake Guide](/guides/bake/) for practical examples and best practices.
|
||||
- [Docker Build Cloud](/guides/docker-build-cloud/_index.md): Learn about Docker's managed build service for faster, scalable, and multi-platform image builds in the cloud.
|
||||
|
||||
@@ -6,9 +6,8 @@ description: >
|
||||
summary: >
|
||||
Learn to automate Docker builds and testing with declarative configurations using Buildx Bake.
|
||||
keywords: bake, buildx, multi-platform, build configuration, hcl, automation
|
||||
tags: [devops]
|
||||
languages: [go]
|
||||
params:
|
||||
tags: [cicd]
|
||||
time: 30 minutes
|
||||
image: /images/guides/bake.webp
|
||||
---
|
||||
@@ -441,9 +440,9 @@ build/
|
||||
└── bin
|
||||
├── bakeme
|
||||
├── linux_amd64
|
||||
│ └── bakeme
|
||||
│ └── bakeme
|
||||
├── linux_arm64
|
||||
│ └── bakeme
|
||||
│ └── bakeme
|
||||
└── linux_riscv64
|
||||
└── bakeme
|
||||
|
||||
@@ -476,17 +475,17 @@ $ tree build/
|
||||
build/
|
||||
└── bin
|
||||
├── debug
|
||||
│ ├── linux_amd64
|
||||
│ │ └── bakeme
|
||||
│ ├── linux_arm64
|
||||
│ │ └── bakeme
|
||||
│ └── linux_riscv64
|
||||
│ └── bakeme
|
||||
│ ├── linux_amd64
|
||||
│ │ └── bakeme
|
||||
│ ├── linux_arm64
|
||||
│ │ └── bakeme
|
||||
│ └── linux_riscv64
|
||||
│ └── bakeme
|
||||
└── release
|
||||
├── linux_amd64
|
||||
│ └── bakeme
|
||||
│ └── bakeme
|
||||
├── linux_arm64
|
||||
│ └── bakeme
|
||||
│ └── bakeme
|
||||
└── linux_riscv64
|
||||
└── bakeme
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
description: Containerize and develop Bun applications using Docker.
|
||||
keywords: getting started, bun
|
||||
title: Bun language-specific guide
|
||||
summary: |
|
||||
Learn how to containerize JavaScript applications with the Bun runtime.
|
||||
linkTitle: Bun
|
||||
aliases:
|
||||
- /guides/bun/configure-ci-cd/
|
||||
- /guides/bun/deploy/
|
||||
languages: [js]
|
||||
tags: [dhi]
|
||||
params:
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
The Bun getting started guide teaches you how to create a containerized Bun application using Docker.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) for his contribution to this guide.
|
||||
|
||||
## What will you learn?
|
||||
|
||||
* Containerize and run a Bun application using Docker
|
||||
* Set up a local environment to develop a Bun application using containers
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Basic understanding of JavaScript is assumed.
|
||||
- You must have familiarity with Docker concepts like containers, images, and Dockerfiles. If you are new to Docker, you can start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
After completing the Bun getting started modules, you should be able to containerize your own Bun application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing Bun application.
|
||||
@@ -1,72 +0,0 @@
|
||||
---
|
||||
title: Use containers for Bun development
|
||||
linkTitle: Develop your app
|
||||
weight: 20
|
||||
keywords: bun, local, development
|
||||
description: Learn how to develop your Bun application locally.
|
||||
aliases:
|
||||
- /language/bun/develop/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Containerize a Bun application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
|
||||
## Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/bun-docker.git && cd bun-docker
|
||||
```
|
||||
|
||||
## Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you
|
||||
edit and save your code. For more details about Compose Watch, see [Use Compose
|
||||
Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yml` file in an IDE or text editor and then add the Compose Watch instructions. The following example shows how to add Compose Watch to your `compose.yml` file.
|
||||
|
||||
```yaml {hl_lines="9-12",linenos=true}
|
||||
services:
|
||||
server:
|
||||
image: bun-server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "3000:3000"
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `server.js` you will see the changes in real time without re-building the image.
|
||||
|
||||
To test it out, open the `server.js` file in your favorite text editor and change the message from `{"Status" : "OK"}` to `{"Status" : "Updated"}`. Save the file and refresh your browser at `http://localhost:3000`. You should see the updated message.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you also learned how to use Compose Watch to automatically rebuild and run your container when you update your code.
|
||||
|
||||
Related information:
|
||||
- [Compose file reference](/reference/compose-file/)
|
||||
- [Compose file watch](/manuals/compose/how-tos/file-watch.md)
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md)
|
||||
|
||||
@@ -1,18 +1,47 @@
|
||||
---
|
||||
title: Containerize a Bun application
|
||||
linkTitle: Containerize your app
|
||||
weight: 10
|
||||
keywords: bun, containerize, initialize
|
||||
description: Learn how to containerize a Bun application.
|
||||
description: Containerize and develop Bun applications using Docker.
|
||||
keywords: getting started, bun
|
||||
title: Bun language-specific guide
|
||||
summary: |
|
||||
Learn how to containerize JavaScript applications with the Bun runtime.
|
||||
linkTitle: Bun
|
||||
aliases:
|
||||
- /language/bun/containerize/
|
||||
- /guides/bun/configure-ci-cd/
|
||||
- /guides/bun/containerize/
|
||||
- /guides/bun/deploy/
|
||||
- /guides/bun/develop/
|
||||
params:
|
||||
tags: [languages]
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
The Bun getting started guide teaches you how to create a containerized Bun application using Docker.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) for his contribution to this guide.
|
||||
|
||||
## What will you learn?
|
||||
|
||||
- Containerize and run a Bun application using Docker
|
||||
- Set up a local environment to develop a Bun application using containers
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
- Basic understanding of JavaScript is assumed.
|
||||
- You must have familiarity with Docker concepts like containers, images, and Dockerfiles. If you are new to Docker, you can start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
## Overview
|
||||
After completing the Bun getting started modules, you should be able to containerize your own Bun application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing Bun application.
|
||||
|
||||
## Containerize a Bun application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
### Overview
|
||||
|
||||
For a long time, Node.js has been the de-facto runtime for server-side
|
||||
JavaScript applications. Recent years have seen a rise in new alternative
|
||||
@@ -29,7 +58,7 @@ dependencies. Also, as it's fairly a new runtime, getting a consistent
|
||||
development environment for Bun can be challenging. Docker can help you set up
|
||||
a consistent development environment for Bun.
|
||||
|
||||
## Get the sample application
|
||||
### Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change
|
||||
directory to a directory that you want to work in, and run the following
|
||||
@@ -50,7 +79,7 @@ You should now have the following contents in your `bun-docker` directory.
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
## Create a Dockerfile
|
||||
### Create a Dockerfile
|
||||
|
||||
Before creating a Dockerfile, you need to choose a base image. You can either use the [Bun Docker Official Image](https://hub.docker.com/r/oven/bun) or a Docker Hardened Image (DHI) from the [Hardened Image catalog](https://hub.docker.com/hardened-images/catalog).
|
||||
|
||||
@@ -62,6 +91,7 @@ Choosing DHI offers the advantage of a production-ready image that is lightweigh
|
||||
Docker Hardened Images (DHIs) are available for Bun in the [Docker Hardened Images catalog](https://hub.docker.com/hardened-images/catalog/dhi/bun). You can pull DHIs directly from the `dhi.io` registry.
|
||||
|
||||
1. Sign in to the DHI registry:
|
||||
|
||||
```console
|
||||
$ docker login dhi.io
|
||||
```
|
||||
@@ -125,7 +155,7 @@ In addition to specifying the base image, the Dockerfile also:
|
||||
- Exposes port 3000, where the API is listening for requests.
|
||||
- And finally, starts the server when the container launches with the command `bun server.js`.
|
||||
|
||||
## Run the application
|
||||
### Run the application
|
||||
|
||||
Inside the `bun-docker` directory, run the following command in a terminal.
|
||||
|
||||
@@ -137,7 +167,7 @@ Open a browser and view the application at [http://localhost:3000](http://localh
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
### Run the application in the background
|
||||
#### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `bun-docker` directory, run the following command
|
||||
@@ -149,27 +179,73 @@ $ docker compose up --build -d
|
||||
|
||||
Open a browser and view the application at [http://localhost:3000](http://localhost:3000).
|
||||
|
||||
|
||||
In the terminal, run the following command to stop the application.
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Use containers for Bun development
|
||||
|
||||
In this section, you learned how you can containerize and run your Bun
|
||||
application using Docker.
|
||||
### Prerequisites
|
||||
|
||||
Complete [Containerize a Bun application](./).
|
||||
|
||||
### Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
|
||||
### Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/bun-docker.git && cd bun-docker
|
||||
```
|
||||
|
||||
### Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you
|
||||
edit and save your code. For more details about Compose Watch, see [Use Compose
|
||||
Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yml` file in an IDE or text editor and then add the Compose Watch instructions. The following example shows how to add Compose Watch to your `compose.yml` file.
|
||||
|
||||
```yaml {hl_lines="9-12",linenos=true}
|
||||
services:
|
||||
server:
|
||||
image: bun-server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "3000:3000"
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `server.js` you will see the changes in real time without re-building the image.
|
||||
|
||||
To test it out, open the `server.js` file in your favorite text editor and change the message from `{"Status" : "OK"}` to `{"Status" : "Updated"}`. Save the file and refresh your browser at `http://localhost:3000`. You should see the updated message.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you also learned how to use Compose Watch to automatically rebuild and run your container when you update your code.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Dockerfile reference](/reference/dockerfile.md)
|
||||
- [.dockerignore file](/reference/dockerfile.md#dockerignore-file)
|
||||
- [Docker Compose overview](/manuals/compose/_index.md)
|
||||
- [Compose file reference](/reference/compose-file/_index.md)
|
||||
- [Docker Hardened Images](/dhi/)
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how you can develop your application using
|
||||
containers.
|
||||
- [Compose file reference](/reference/compose-file/)
|
||||
- [Compose file watch](/manuals/compose/how-tos/file-watch.md)
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md)
|
||||
@@ -5,8 +5,8 @@ summary: |
|
||||
Connect Claude Code to Docker Model Runner with the Anthropic-compatible API,
|
||||
package `gpt-oss` with a larger context window, and inspect requests.
|
||||
keywords: ai, claude code, docker model runner, anthropic, local models, coding assistant
|
||||
tags: [ai]
|
||||
params:
|
||||
tags: [ai]
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ summary: |
|
||||
isolated microVM that talks to a local model on your host through the
|
||||
Anthropic-compatible API.
|
||||
keywords: ai, claude code, docker model runner, docker sandboxes, sbx, anthropic, local models, coding assistant
|
||||
tags: [ai]
|
||||
params:
|
||||
tags: [ai]
|
||||
time: 15 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@ description: Learn how to build Docker Compose projects with Docker Buildx Bake
|
||||
summary: |
|
||||
This guide demonstrates how you can use Bake to build production-grade images for Docker Compose projects.
|
||||
keywords: docker compose, bake, buildx, multi-service, production builds, build configuration
|
||||
languages: []
|
||||
tags: [devops]
|
||||
params:
|
||||
tags: [cicd]
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
@@ -211,7 +210,7 @@ $ docker buildx bake
|
||||
Start by redefining the default build group that Bake executes. The current
|
||||
default group includes a `seed` target — a Compose service used solely to
|
||||
populate the database with mock data. Since this target doesn't produce a
|
||||
production image, it doesn’t need to be included in the build group.
|
||||
production image, it doesn't need to be included in the build group.
|
||||
|
||||
To customize the build configuration that Bake uses, create a new file at the
|
||||
root of the repository, alongside your `compose.yaml` file, named
|
||||
@@ -399,5 +398,5 @@ For more information about how to use Bake, check out these resources:
|
||||
- [Bake documentation](/manuals/build/bake/_index.md)
|
||||
- [Building with Bake from a Compose file](/manuals/build/bake/compose-file.md)
|
||||
- [Bake file reference](/manuals/build/bake/reference.md)
|
||||
- [Mastering multi-platform builds, testing, and more with Docker Buildx Bake](/guides/bake/index.md)
|
||||
- [Mastering multi-platform builds, testing, and more with Docker Buildx Bake](/guides/bake/)
|
||||
- [Bake GitHub Action](https://github.com/docker/bake-action)
|
||||
@@ -6,8 +6,8 @@ summary: |
|
||||
description: |
|
||||
Use containers in your local development loop to develop and test faster… even if your main app isn't running in containers.
|
||||
keywords: containers, local development, dependent services, testing, debugging, development environment
|
||||
tags: [app-dev]
|
||||
params:
|
||||
tags: [cicd]
|
||||
image: images/learning-paths/container-supported-development.png
|
||||
time: 20 minutes
|
||||
resource_links: []
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
title: C++ language-specific guide
|
||||
linkTitle: C++
|
||||
description: Containerize and develop C++ applications using Docker.
|
||||
keywords: getting started, c++
|
||||
summary: |
|
||||
This guide explains how to containerize C++ applications using Docker.
|
||||
toc_min: 1
|
||||
toc_max: 2
|
||||
aliases:
|
||||
- /language/cpp/
|
||||
- /guides/language/cpp/
|
||||
- /guides/cpp/configure-ci-cd/
|
||||
- /language/cpp/configure-ci-cd/
|
||||
- /guides/language/cpp/configure-ci-cd/
|
||||
- /guides/cpp/deploy/
|
||||
- /language/cpp/deploy/
|
||||
- /guides/language/cpp/deploy/
|
||||
- /guides/cpp/security/
|
||||
languages: [cpp]
|
||||
params:
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
The C++ getting started guide teaches you how to create a containerized C++ application using Docker. In this guide, you'll learn how to:
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) and [Mohammad-Ali A'râbi](https://twitter.com/MohammadAliEN) for their contribution to this guide.
|
||||
|
||||
- Containerize and run a C++ application using a multi-stage Docker build
|
||||
- Build and run a C++ application using Docker Compose
|
||||
- Set up a local environment to develop a C++ application using containers
|
||||
|
||||
After completing the C++ getting started modules, you should be able to containerize your own C++ application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing C++ application.
|
||||
@@ -1,93 +0,0 @@
|
||||
---
|
||||
title: Containerize a C++ application
|
||||
linkTitle: Containerize
|
||||
weight: 10
|
||||
keywords: C++, containerize, initialize
|
||||
description: Learn how to use Docker Compose to build and run a C++ application.
|
||||
aliases:
|
||||
- /language/cpp/containerize/
|
||||
- /guides/language/cpp/containerize/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
## Overview
|
||||
|
||||
This section walks you through containerizing and running a C++ application, using Docker Compose.
|
||||
|
||||
## Get the sample application
|
||||
|
||||
We're using the same sample repository that you used in the previous sections of this guide. If you haven't already cloned the repository, clone it now:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/c-plus-plus-docker.git
|
||||
```
|
||||
|
||||
You should now have the following contents in your `c-plus-plus-docker` (root)
|
||||
directory.
|
||||
|
||||
```text
|
||||
├── c-plus-plus-docker/
|
||||
│ ├── compose.yml
|
||||
│ ├── Dockerfile
|
||||
│ ├── LICENSE
|
||||
│ ├── ok_api.cpp
|
||||
│ └── README.md
|
||||
|
||||
```
|
||||
|
||||
To learn more about the files in the repository, see the following:
|
||||
|
||||
- [Dockerfile](/reference/dockerfile.md)
|
||||
- [.dockerignore](/reference/dockerfile.md#dockerignore-file)
|
||||
- [compose.yml](/reference/compose-file/_index.md)
|
||||
|
||||
## Run the application
|
||||
|
||||
Inside the `c-plus-plus-docker` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You will see a message `{"Status" : "OK"}` in the browser.
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `c-plus-plus-docker` directory, run the following command
|
||||
in a terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build -d
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080).
|
||||
|
||||
In the terminal, run the following command to stop the application.
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
For more information about Compose commands, see the [Compose CLI
|
||||
reference](/reference/cli/docker/compose/).
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how you can containerize and run your C++
|
||||
application using Docker.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Docker Compose overview](/manuals/compose/_index.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how you can develop your application using
|
||||
containers.
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
title: Use containers for C++ development
|
||||
linkTitle: Develop your app
|
||||
weight: 20
|
||||
keywords: C++, local, development
|
||||
description: Learn how to develop your C++ application locally.
|
||||
aliases:
|
||||
- /language/cpp/develop/
|
||||
- /guides/language/cpp/develop/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Containerize a C++ application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
|
||||
## Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/c-plus-plus-docker.git && cd c-plus-plus-docker
|
||||
```
|
||||
|
||||
## Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you
|
||||
edit and save your code. For more details about Compose Watch, see [Use Compose
|
||||
Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yml` file in an IDE or text editor and then add the Compose Watch instructions. The following example shows how to add Compose Watch to your `compose.yml` file.
|
||||
|
||||
```yaml {hl_lines="11-14",linenos=true}
|
||||
services:
|
||||
ok-api:
|
||||
image: ok-api
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8080:8080"
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `ok_api.cpp` you will see the changes in real time without re-building the image.
|
||||
|
||||
To test it out, open the `ok_api.cpp` file in your favorite text editor and change the message from `{"Status" : "OK"}` to `{"Status" : "Updated"}`. Save the file and refresh your browser at [http://localhost:8080](http://localhost:8080). You should see the updated message.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you also learned how to use Compose Watch to automatically rebuild and run your container when you update your code.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Compose file reference](/reference/compose-file/)
|
||||
- [Compose file watch](/manuals/compose/how-tos/file-watch.md)
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md)
|
||||
|
||||
276
content/guides/cpp/index.md
Normal file
276
content/guides/cpp/index.md
Normal file
@@ -0,0 +1,276 @@
|
||||
---
|
||||
title: C++ language-specific guide
|
||||
linkTitle: C++
|
||||
description: Containerize and develop C++ applications using Docker.
|
||||
keywords: getting started, c++
|
||||
summary: |
|
||||
This guide explains how to containerize C++ applications using Docker.
|
||||
aliases:
|
||||
- /language/cpp/
|
||||
- /guides/language/cpp/
|
||||
- /language/cpp/containerize/
|
||||
- /language/cpp/develop/
|
||||
- /language/cpp/configure-ci-cd/
|
||||
- /language/cpp/deploy/
|
||||
- /guides/cpp/configure-ci-cd/
|
||||
- /guides/cpp/containerize/
|
||||
- /guides/cpp/deploy/
|
||||
- /guides/cpp/develop/
|
||||
- /guides/cpp/multistage/
|
||||
- /guides/cpp/security/
|
||||
params:
|
||||
tags: [languages]
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
The C++ getting started guide teaches you how to create a containerized C++ application using Docker. In this guide, you'll learn how to:
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) and [Mohammad-Ali A'râbi](https://twitter.com/MohammadAliEN) for their contribution to this guide.
|
||||
|
||||
- Containerize and run a C++ application using a multi-stage Docker build
|
||||
- Build and run a C++ application using Docker Compose
|
||||
- Set up a local environment to develop a C++ application using containers
|
||||
|
||||
After completing the C++ getting started modules, you should be able to containerize your own C++ application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing C++ application.
|
||||
|
||||
## Create a multi-stage build for your C++ application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
### Overview
|
||||
|
||||
This section walks you through creating a multi-stage Docker build for a C++ application.
|
||||
A multi-stage build is a Docker feature that allows you to use different base images for different stages of the build process,
|
||||
so you can optimize the size of your final image and separate build dependencies from runtime dependencies.
|
||||
|
||||
The standard practice for compiled languages like C++ is to have a build stage that compiles the code and a runtime stage that runs the compiled binary,
|
||||
because the build dependencies are not needed at runtime.
|
||||
|
||||
### Get the sample application
|
||||
|
||||
Let's use a simple C++ application that prints `Hello, World!` to the terminal. To do so, clone the sample repository to use with this guide:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/dockersamples/c-plus-plus-docker.git
|
||||
```
|
||||
|
||||
The example for this section is under the `hello` directory in the repository. Get inside it and take a look at the files:
|
||||
|
||||
```bash
|
||||
$ cd c-plus-plus-docker/hello
|
||||
$ ls
|
||||
```
|
||||
|
||||
You should see the following files:
|
||||
|
||||
```text
|
||||
Dockerfile hello.cpp
|
||||
```
|
||||
|
||||
### Check the Dockerfile
|
||||
|
||||
Open the `Dockerfile` in an IDE or text editor. The `Dockerfile` contains the instructions for building the Docker image.
|
||||
|
||||
```Dockerfile
|
||||
# Stage 1: Build stage
|
||||
FROM ubuntu:latest AS build
|
||||
|
||||
# Install build-essential for compiling C++ code
|
||||
RUN apt-get update && apt-get install -y build-essential
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the source code into the container
|
||||
COPY hello.cpp .
|
||||
|
||||
# Compile the C++ code statically to ensure it doesn't depend on runtime libraries
|
||||
RUN g++ -o hello hello.cpp -static
|
||||
|
||||
# Stage 2: Runtime stage
|
||||
FROM scratch
|
||||
|
||||
# Copy the static binary from the build stage
|
||||
COPY --from=build /app/hello /hello
|
||||
|
||||
# Command to run the binary
|
||||
CMD ["/hello"]
|
||||
```
|
||||
|
||||
The `Dockerfile` has two stages:
|
||||
|
||||
1. **Build stage**: This stage uses the `ubuntu:latest` image to compile the C++ code and create a static binary.
|
||||
2. **Runtime stage**: This stage uses the `scratch` image, which is an empty image, to copy the static binary from the build stage and run it.
|
||||
|
||||
### Build the Docker image
|
||||
|
||||
To build the Docker image, run the following command in the `hello` directory:
|
||||
|
||||
```bash
|
||||
$ docker build -t hello .
|
||||
```
|
||||
|
||||
The `-t` flag tags the image with the name `hello`.
|
||||
|
||||
### Run the Docker container
|
||||
|
||||
To run the Docker container, use the following command:
|
||||
|
||||
```bash
|
||||
$ docker run hello
|
||||
```
|
||||
|
||||
You should see the output `Hello, World!` in the terminal.
|
||||
|
||||
Because the final image uses an empty `scratch` base, it contains only the
|
||||
static binary and none of the build dependencies or usual OS tools. For
|
||||
example, you can't run a simple `ls` command in the container:
|
||||
|
||||
```bash
|
||||
$ docker run hello ls
|
||||
```
|
||||
|
||||
The absence of a shell and other tools keeps the image small and reduces its
|
||||
attack surface.
|
||||
|
||||
## Containerize a C++ application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
### Overview
|
||||
|
||||
This section walks you through containerizing and running a C++ application, using Docker Compose.
|
||||
|
||||
### Get the sample application
|
||||
|
||||
We're using the same sample repository that you used in the previous sections of this guide. If you haven't already cloned the repository, clone it now:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/c-plus-plus-docker.git
|
||||
```
|
||||
|
||||
You should now have the following contents in your `c-plus-plus-docker` (root)
|
||||
directory.
|
||||
|
||||
```text
|
||||
├── c-plus-plus-docker/
|
||||
│ ├── compose.yml
|
||||
│ ├── Dockerfile
|
||||
│ ├── LICENSE
|
||||
│ ├── ok_api.cpp
|
||||
│ └── README.md
|
||||
|
||||
```
|
||||
|
||||
To learn more about the files in the repository, see the following:
|
||||
|
||||
- [Dockerfile](/reference/dockerfile.md)
|
||||
- [.dockerignore](/reference/dockerfile.md#dockerignore-file)
|
||||
- [compose.yml](/reference/compose-file/_index.md)
|
||||
|
||||
### Run the application
|
||||
|
||||
Inside the `c-plus-plus-docker` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You will see a message `{"Status" : "OK"}` in the browser.
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
#### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `c-plus-plus-docker` directory, run the following command
|
||||
in a terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build -d
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080).
|
||||
|
||||
In the terminal, run the following command to stop the application.
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
For more information about Compose commands, see the [Compose CLI
|
||||
reference](/reference/cli/docker/compose/).
|
||||
|
||||
## Use containers for C++ development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Complete [Containerize a C++ application](./).
|
||||
|
||||
### Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
|
||||
### Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/c-plus-plus-docker.git && cd c-plus-plus-docker
|
||||
```
|
||||
|
||||
### Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you
|
||||
edit and save your code. For more details about Compose Watch, see [Use Compose
|
||||
Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yml` file in an IDE or text editor and then add the Compose Watch instructions. The following example shows how to add Compose Watch to your `compose.yml` file.
|
||||
|
||||
```yaml {hl_lines="11-14",linenos=true}
|
||||
services:
|
||||
ok-api:
|
||||
image: ok-api
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8080:8080"
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `ok_api.cpp` you will see the changes in real time without re-building the image.
|
||||
|
||||
To test it out, open the `ok_api.cpp` file in your favorite text editor and change the message from `{"Status" : "OK"}` to `{"Status" : "Updated"}`. Save the file and refresh your browser at [http://localhost:8080](http://localhost:8080). You should see the updated message.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you also learned how to use Compose Watch to automatically rebuild and run your container when you update your code.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Compose file reference](/reference/compose-file/)
|
||||
- [Compose file watch](/manuals/compose/how-tos/file-watch.md)
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md)
|
||||
@@ -1,112 +0,0 @@
|
||||
---
|
||||
title: Create a multi-stage build for your C++ application
|
||||
linkTitle: Multi-stage build
|
||||
weight: 5
|
||||
keywords: C++, containerize, multi-stage
|
||||
description: Learn how to create a multi-stage build for a C++ application.
|
||||
aliases:
|
||||
- /language/cpp/multistage/
|
||||
- /guides/language/cpp/multistage/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
## Overview
|
||||
|
||||
This section walks you through creating a multi-stage Docker build for a C++ application.
|
||||
A multi-stage build is a Docker feature that allows you to use different base images for different stages of the build process,
|
||||
so you can optimize the size of your final image and separate build dependencies from runtime dependencies.
|
||||
|
||||
The standard practice for compiled languages like C++ is to have a build stage that compiles the code and a runtime stage that runs the compiled binary,
|
||||
because the build dependencies are not needed at runtime.
|
||||
|
||||
## Get the sample application
|
||||
|
||||
Let's use a simple C++ application that prints `Hello, World!` to the terminal. To do so, clone the sample repository to use with this guide:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/dockersamples/c-plus-plus-docker.git
|
||||
```
|
||||
|
||||
The example for this section is under the `hello` directory in the repository. Get inside it and take a look at the files:
|
||||
|
||||
```bash
|
||||
$ cd c-plus-plus-docker/hello
|
||||
$ ls
|
||||
```
|
||||
|
||||
You should see the following files:
|
||||
|
||||
```text
|
||||
Dockerfile hello.cpp
|
||||
```
|
||||
|
||||
## Check the Dockerfile
|
||||
|
||||
Open the `Dockerfile` in an IDE or text editor. The `Dockerfile` contains the instructions for building the Docker image.
|
||||
|
||||
```Dockerfile
|
||||
# Stage 1: Build stage
|
||||
FROM ubuntu:latest AS build
|
||||
|
||||
# Install build-essential for compiling C++ code
|
||||
RUN apt-get update && apt-get install -y build-essential
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the source code into the container
|
||||
COPY hello.cpp .
|
||||
|
||||
# Compile the C++ code statically to ensure it doesn't depend on runtime libraries
|
||||
RUN g++ -o hello hello.cpp -static
|
||||
|
||||
# Stage 2: Runtime stage
|
||||
FROM scratch
|
||||
|
||||
# Copy the static binary from the build stage
|
||||
COPY --from=build /app/hello /hello
|
||||
|
||||
# Command to run the binary
|
||||
CMD ["/hello"]
|
||||
```
|
||||
|
||||
The `Dockerfile` has two stages:
|
||||
|
||||
1. **Build stage**: This stage uses the `ubuntu:latest` image to compile the C++ code and create a static binary.
|
||||
2. **Runtime stage**: This stage uses the `scratch` image, which is an empty image, to copy the static binary from the build stage and run it.
|
||||
|
||||
## Build the Docker image
|
||||
|
||||
To build the Docker image, run the following command in the `hello` directory:
|
||||
|
||||
```bash
|
||||
$ docker build -t hello .
|
||||
```
|
||||
|
||||
The `-t` flag tags the image with the name `hello`.
|
||||
|
||||
## Run the Docker container
|
||||
|
||||
To run the Docker container, use the following command:
|
||||
|
||||
```bash
|
||||
$ docker run hello
|
||||
```
|
||||
|
||||
You should see the output `Hello, World!` in the terminal.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to create a multi-stage build for a C++ application. Multi-stage builds help you optimize the size of your final image and separate build dependencies from runtime dependencies.
|
||||
In this example, the final image only contains the static binary and doesn't include any build dependencies.
|
||||
|
||||
As the image has an empty base, the usual OS tools are also absent. So, for example, you can't run a simple `ls` command in the container:
|
||||
|
||||
```bash
|
||||
$ docker run hello ls
|
||||
```
|
||||
|
||||
This makes the image very lightweight and secure.
|
||||
@@ -4,10 +4,10 @@ keywords: database, mysql
|
||||
title: Use containerized databases
|
||||
summary: |
|
||||
Learn how to effectively run and manage databases as containers.
|
||||
tags: [databases]
|
||||
aliases:
|
||||
- /guides/use-case/databases/
|
||||
params:
|
||||
tags: [databases]
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
description: Containerize and develop Deno applications using Docker.
|
||||
keywords: getting started, deno
|
||||
title: Deno language-specific guide
|
||||
summary: |
|
||||
Learn how to containerize JavaScript applications with the Deno runtime using Docker.
|
||||
linkTitle: Deno
|
||||
aliases:
|
||||
- /guides/deno/configure-ci-cd/
|
||||
- /guides/deno/deploy/
|
||||
languages: [js]
|
||||
tags: [dhi]
|
||||
params:
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
The Deno getting started guide teaches you how to create a containerized Deno application using Docker.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) for his contribution to this guide.
|
||||
|
||||
## What will you learn?
|
||||
|
||||
* Containerize and run a Deno application using Docker
|
||||
* Set up a local environment to develop a Deno application using containers
|
||||
* Use Docker Compose to run the application.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Basic understanding of JavaScript is assumed.
|
||||
- You must have familiarity with Docker concepts like containers, images, and Dockerfiles. If you are new to Docker, you can start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
After completing the Deno getting started modules, you should be able to containerize your own Deno application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing Deno application.
|
||||
@@ -1,72 +0,0 @@
|
||||
---
|
||||
title: Use containers for Deno development
|
||||
linkTitle: Develop your app
|
||||
weight: 20
|
||||
keywords: deno, local, development
|
||||
description: Learn how to develop your Deno application locally.
|
||||
aliases:
|
||||
- /language/deno/develop/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Containerize a Deno application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
|
||||
## Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/docker-deno.git && cd docker-deno
|
||||
```
|
||||
|
||||
## Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you
|
||||
edit and save your code. For more details about Compose Watch, see [Use Compose
|
||||
Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yml` file in an IDE or text editor and then add the Compose Watch instructions. The following example shows how to add Compose Watch to your `compose.yml` file.
|
||||
|
||||
```yaml {hl_lines="9-12",linenos=true}
|
||||
services:
|
||||
server:
|
||||
image: deno-server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8000:8000"
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `server.ts` you will see the changes in real time without re-building the image.
|
||||
|
||||
To test it out, open the `server.ts` file in your favorite text editor and change the message from `{"Status" : "OK"}` to `{"Status" : "Updated"}`. Save the file and refresh your browser at `http://localhost:8000`. You should see the updated message.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you also learned how to use Compose Watch to automatically rebuild and run your container when you update your code.
|
||||
|
||||
Related information:
|
||||
- [Compose file reference](/reference/compose-file/)
|
||||
- [Compose file watch](/manuals/compose/how-tos/file-watch.md)
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md)
|
||||
|
||||
@@ -1,24 +1,54 @@
|
||||
---
|
||||
title: Containerize a Deno application
|
||||
linkTitle: Containerize your app
|
||||
weight: 10
|
||||
keywords: deno, containerize, initialize
|
||||
description: Learn how to containerize a Deno application.
|
||||
description: Containerize and develop Deno applications using Docker.
|
||||
keywords: getting started, deno
|
||||
title: Deno language-specific guide
|
||||
summary: |
|
||||
Learn how to containerize JavaScript applications with the Deno runtime using Docker.
|
||||
linkTitle: Deno
|
||||
aliases:
|
||||
- /language/deno/containerize/
|
||||
- /guides/deno/configure-ci-cd/
|
||||
- /guides/deno/containerize/
|
||||
- /guides/deno/deploy/
|
||||
- /guides/deno/develop/
|
||||
params:
|
||||
tags: [languages]
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
The Deno getting started guide teaches you how to create a containerized Deno application using Docker.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) for his contribution to this guide.
|
||||
|
||||
## What will you learn?
|
||||
|
||||
- Containerize and run a Deno application using Docker
|
||||
- Set up a local environment to develop a Deno application using containers
|
||||
- Use Docker Compose to run the application.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
- Basic understanding of JavaScript is assumed.
|
||||
- You must have familiarity with Docker concepts like containers, images, and Dockerfiles. If you are new to Docker, you can start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
## Overview
|
||||
After completing the Deno getting started modules, you should be able to containerize your own Deno application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing Deno application.
|
||||
|
||||
## Containerize a Deno application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
### Overview
|
||||
|
||||
For a long time, Node.js has been the go-to runtime for server-side JavaScript applications. However, recent years have introduced new alternative runtimes, including [Deno](https://deno.land/). Like Node.js, Deno is a JavaScript and TypeScript runtime, but it takes a fresh approach with modern security features, a built-in standard library, and native support for TypeScript.
|
||||
|
||||
Why develop Deno applications with Docker? Having a choice of runtimes is exciting, but managing multiple runtimes and their dependencies consistently across environments can be tricky. This is where Docker proves invaluable. Using containers to create and destroy environments on demand simplifies runtime management and ensures consistency. Additionally, as Deno continues to grow and evolve, Docker helps establish a reliable and reproducible development environment, minimizing setup challenges and streamlining the workflow.
|
||||
|
||||
## Get the sample application
|
||||
### Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change
|
||||
directory to a directory that you want to work in, and run the following
|
||||
@@ -39,7 +69,7 @@ You should now have the following contents in your `deno-docker` directory.
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
## Understand the sample application
|
||||
### Understand the sample application
|
||||
|
||||
The sample application is a simple Deno application that uses the Oak framework to create a simple API that returns a JSON response. The application listens on port 8000 and returns a message `{"Status" : "OK"}` when you access the application in a browser.
|
||||
|
||||
@@ -63,7 +93,7 @@ console.log("Server running on http://localhost:8000");
|
||||
await app.listen({ port: 8000 });
|
||||
```
|
||||
|
||||
## Create a Dockerfile
|
||||
### Create a Dockerfile
|
||||
|
||||
Before creating a Dockerfile, you need to choose a base image. You can either use the [Deno Docker Official Image](https://hub.docker.com/r/denoland/deno) or a Docker Hardened Image (DHI) from the [Hardened Image catalog](https://hub.docker.com/hardened-images/catalog).
|
||||
|
||||
@@ -147,7 +177,7 @@ In addition to specifying the base image, the Dockerfile also:
|
||||
- Runs the Deno server using the `CMD` instruction.
|
||||
- Uses the `--allow-net` flag to allow network access to the application. The `server.ts` file uses the Oak framework to create a simple API that listens on port 8000.
|
||||
|
||||
## Run the application
|
||||
### Run the application
|
||||
|
||||
Make sure you are in the `deno-docker` directory. Run the following command in a terminal to build and run the application.
|
||||
|
||||
@@ -159,7 +189,7 @@ Open a browser and view the application at [http://localhost:8000](http://localh
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
### Run the application in the background
|
||||
#### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `deno-docker` directory, run the following command
|
||||
@@ -171,27 +201,73 @@ $ docker compose up --build -d
|
||||
|
||||
Open a browser and view the application at [http://localhost:8000](http://localhost:8000).
|
||||
|
||||
|
||||
In the terminal, run the following command to stop the application.
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
## Summary
|
||||
## Use containers for Deno development
|
||||
|
||||
In this section, you learned how you can containerize and run your Deno
|
||||
application using Docker.
|
||||
### Prerequisites
|
||||
|
||||
Complete [Containerize a Deno application](./).
|
||||
|
||||
### Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
|
||||
### Get the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/docker-deno.git && cd docker-deno
|
||||
```
|
||||
|
||||
### Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you
|
||||
edit and save your code. For more details about Compose Watch, see [Use Compose
|
||||
Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yml` file in an IDE or text editor and then add the Compose Watch instructions. The following example shows how to add Compose Watch to your `compose.yml` file.
|
||||
|
||||
```yaml {hl_lines="9-12",linenos=true}
|
||||
services:
|
||||
server:
|
||||
image: deno-server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8000:8000"
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `server.ts` you will see the changes in real time without re-building the image.
|
||||
|
||||
To test it out, open the `server.ts` file in your favorite text editor and change the message from `{"Status" : "OK"}` to `{"Status" : "Updated"}`. Save the file and refresh your browser at `http://localhost:8000`. You should see the updated message.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you also learned how to use Compose Watch to automatically rebuild and run your container when you update your code.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Dockerfile reference](/reference/dockerfile.md)
|
||||
- [.dockerignore file](/reference/dockerfile.md#dockerignore-file)
|
||||
- [Docker Compose overview](/manuals/compose/_index.md)
|
||||
- [Compose file reference](/reference/compose-file/_index.md)
|
||||
- [Docker Hardened Images](/dhi/)
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how you can develop your application using
|
||||
containers.
|
||||
- [Compose file reference](/reference/compose-file/)
|
||||
- [Compose file watch](/manuals/compose/how-tos/file-watch.md)
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md)
|
||||
@@ -4,9 +4,8 @@ description: &desc Mocking OAuth services in testing with Dex
|
||||
keywords: Dex, container-supported development
|
||||
linktitle: Mocking OAuth services with Dex
|
||||
summary: *desc
|
||||
tags: [app-dev, distributed-systems]
|
||||
languages: []
|
||||
params:
|
||||
tags: [testing]
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ title: Secure a Backstage application with Docker Hardened Images
|
||||
description: Secure a Backstage developer portal using Docker Hardened Images, covering native module compilation, Socket Firewall protection, and distroless runtime images.
|
||||
summary: Learn how to secure a Backstage developer portal using Docker Hardened Images (DHI), handle native module compilation with better-sqlite3, add Socket Firewall protection during dependency installation, and produce a distroless runtime image using DHI customizations.
|
||||
keywords: docker hardened images, dhi, backstage, CNCF, developer portal, node.js, native modules, sqlite, better-sqlite3, distroless, socket firewall, dhictl, multi-stage build
|
||||
tags: ["Docker Hardened Images", "dhi"]
|
||||
params:
|
||||
tags: [security]
|
||||
proficiencyLevel: Intermediate
|
||||
time: 45 minutes
|
||||
prerequisites:
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
title: Migrate to DHI from Docker Official Images
|
||||
summary: Step-by-step guide to migrate from Docker Official Images to Docker Hardened Images
|
||||
keywords: docker hardened images, dhi, docker official images, migration, secure images
|
||||
type: redirect
|
||||
target: /dhi/migration/migrate-from-doi/
|
||||
tags: [dhi]
|
||||
languages: []
|
||||
params:
|
||||
time: 10 minutes
|
||||
featured: true
|
||||
image: /images/guides/dhi-migrate-doi.webp
|
||||
---
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
title: Migrate to DHI from Wolfi
|
||||
summary: Step-by-step guide to migrate from Wolfi to Docker Hardened Images
|
||||
keywords: docker hardened images, dhi, wolfi, migration, secure images, distroless
|
||||
type: redirect
|
||||
target: /dhi/migration/migrate-from-wolfi/
|
||||
tags: [dhi]
|
||||
languages: []
|
||||
params:
|
||||
time: 10 minutes
|
||||
featured: true
|
||||
image: /images/guides/dhi-migrate-wolfi.webp
|
||||
---
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
title: Migrate a Go app to DHI
|
||||
summary: |
|
||||
Example showing how to migrate a Go application to Docker Hardened Images
|
||||
keywords: docker hardened images, dhi, go, golang, migration, secure images
|
||||
type: redirect
|
||||
target: /dhi/migration/examples/go/
|
||||
tags: [dhi]
|
||||
languages: []
|
||||
params:
|
||||
time: 10 minutes
|
||||
featured: true
|
||||
image: /images/guides/dhi-examples-go.webp
|
||||
---
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
title: Migrate a Node.js app to DHI
|
||||
summary: |
|
||||
Example showing how to migrate a Node.js application to Docker Hardened
|
||||
Images
|
||||
keywords: docker hardened images, dhi, node.js, nodejs, migration, secure images
|
||||
type: redirect
|
||||
target: /dhi/migration/examples/node/
|
||||
tags: [dhi]
|
||||
languages: []
|
||||
params:
|
||||
time: 10 minutes
|
||||
featured: true
|
||||
image: /images/guides/dhi-examples-nodejs.webp
|
||||
---
|
||||
@@ -3,8 +3,8 @@ title: Use Docker Hardened Images with Red Hat OpenShift
|
||||
description: Deploy Docker Hardened Images on Red Hat OpenShift Container Platform, covering Security Context Constraints, arbitrary user ID assignment, file permissions, and best practices.
|
||||
summary: Learn how to deploy Docker Hardened Images (DHI) on Red Hat OpenShift, configure Security Context Constraints, handle arbitrary user ID assignment, and set file permissions for both runtime and development image variants.
|
||||
keywords: docker hardened images, dhi, openshift, OCP, SCC, security context constraints, non-root, distroless, containers, red hat
|
||||
tags: ["Docker Hardened Images", "dhi"]
|
||||
params:
|
||||
tags: [security]
|
||||
proficiencyLevel: Intermediate
|
||||
time: 30 minutes
|
||||
prerequisites:
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
title: Migrate a Python app to DHI
|
||||
summary: |
|
||||
Example showing how to migrate a Python application to Docker Hardened Images
|
||||
keywords: docker hardened images, dhi, python, migration, secure images
|
||||
type: redirect
|
||||
target: /dhi/migration/examples/python/
|
||||
tags: [dhi]
|
||||
languages: []
|
||||
params:
|
||||
time: 10 minutes
|
||||
featured: true
|
||||
image: /images/guides/dhi-examples-python.webp
|
||||
---
|
||||
@@ -7,8 +7,10 @@ summary: >
|
||||
Scan a Docker Hardened Image with and without VEX and audit every suppression
|
||||
and its justification.
|
||||
keywords: vex, openvex, not_affected, under_investigation, affected, cve, docker scout, dhi, vulnerability
|
||||
tags: [dhi]
|
||||
weight: 1
|
||||
params:
|
||||
tags: [security]
|
||||
featured: true
|
||||
proficiencyLevel: Intermediate
|
||||
time: 25 minutes
|
||||
---
|
||||
|
||||
@@ -8,9 +8,8 @@ summary: |
|
||||
You'll scaffold the project with uv, create a production-ready Dockerfile
|
||||
using a Docker Hardened Image, then add a development stage and Compose Watch
|
||||
for fast iteration.
|
||||
languages: [python]
|
||||
tags: [dhi]
|
||||
params:
|
||||
tags: [security]
|
||||
time: 25 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
title: "Docker Build Cloud: Reclaim your time with fast, multi-architecture builds"
|
||||
linkTitle: Docker Build Cloud
|
||||
description: |
|
||||
Learn how to build and deploy Docker images to the cloud with Docker Build
|
||||
Cloud.
|
||||
summary: |
|
||||
Build applications up to 39x faster using cloud-based resources, shared team
|
||||
cache, and native multi-architecture support.
|
||||
keywords: docker build cloud, cloud builds, multi-architecture, shared cache, ci/cd, build performance
|
||||
tags: [product-demo]
|
||||
aliases:
|
||||
- /learning-paths/docker-build-cloud/
|
||||
params:
|
||||
image: images/learning-paths/build-cloud.png
|
||||
time: 10 minutes
|
||||
resource_links:
|
||||
- title: Product page
|
||||
url: https://www.docker.com/products/build-cloud/
|
||||
- title: Docker Build Cloud overview
|
||||
url: /build-cloud/
|
||||
- title: Subscriptions and features
|
||||
url: "https://www.docker.com/pricing?ref=Docs&refAction=DocsGuidesBuildCloud"
|
||||
- title: Using Docker Build Cloud
|
||||
url: /build-cloud/usage/
|
||||
---
|
||||
|
||||
<!-- 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.
|
||||
|
||||
## 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
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
title: "Demo: Using Docker Build Cloud in CI"
|
||||
description: Learn how to use Docker Build Cloud to build your app faster in CI.
|
||||
keywords: docker build cloud, ci/cd, github actions, cloud builds, build performance
|
||||
weight: 30
|
||||
---
|
||||
|
||||
Docker Build Cloud can significantly decrease the time it takes for your CI builds
|
||||
take to run, saving you time and money.
|
||||
|
||||
Since the builds run remotely, your CI runner can still use the Docker tooling CLI
|
||||
without needing elevated permissions, making your builds more secure by default.
|
||||
|
||||
In this demo, you will see:
|
||||
|
||||
- How to integrate Docker Build Cloud into a variety of CI platforms
|
||||
- How to use Docker Build Cloud in GitHub Actions to build multi-architecture images
|
||||
- Speed differences between a workflow using Docker Build Cloud and a workflow running natively
|
||||
- How to use Docker Build Cloud in a GitLab Pipeline
|
||||
|
||||
{{< youtube-embed "wvLdInoVBGg" >}}
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
title: Common challenges and questions
|
||||
description: Explore common challenges and questions related to Docker Build Cloud.
|
||||
keywords: docker build cloud, faq, troubleshooting, cloud builds, pricing
|
||||
weight: 40
|
||||
---
|
||||
|
||||
### 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?
|
||||
|
||||
Pricing details for Docker Build Cloud can be found on the [pricing page](https://www.docker.com/pricing?ref=Docs&refAction=DocsGuidesBuildCloudFaq).
|
||||
|
||||
### 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 start a trial of Docker Build Cloud. Personal accounts are limited to a
|
||||
single user.
|
||||
|
||||
For teams to receive the shared cache benefit, they must either be on a Docker
|
||||
Team or Docker Business subscription.
|
||||
|
||||
### 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.
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
title: "Demo: set up and use Docker Build Cloud in development"
|
||||
description: Learn how to use Docker Build Cloud for local builds.
|
||||
keywords: docker build cloud, local development, cloud builds, multi-platform, build performance
|
||||
weight: 20
|
||||
---
|
||||
|
||||
With Docker Build Cloud, you can easily shift the build workload from local machines
|
||||
to the cloud, helping you achieve faster build times, especially for multi-platform builds.
|
||||
|
||||
In this demo, you'll see:
|
||||
|
||||
- How to setup the builder locally
|
||||
- How to use Docker Build Cloud with Docker Compose
|
||||
- How the image cache speeds up builds for others on your team
|
||||
|
||||
{{< youtube-embed "oPGq2AP5OtQ" >}}
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
173
content/guides/docker-build-cloud/index.md
Normal file
173
content/guides/docker-build-cloud/index.md
Normal file
@@ -0,0 +1,173 @@
|
||||
---
|
||||
title: "Docker Build Cloud: Reclaim your time with fast, multi-architecture builds"
|
||||
linkTitle: Docker Build Cloud
|
||||
description: |
|
||||
Learn how to build and deploy Docker images to the cloud with Docker Build
|
||||
Cloud.
|
||||
summary: |
|
||||
Build applications up to 39x faster using cloud-based resources, shared team
|
||||
cache, and native multi-architecture support.
|
||||
keywords: docker build cloud, cloud builds, multi-architecture, shared cache, ci/cd, build performance
|
||||
aliases:
|
||||
- /learning-paths/docker-build-cloud/
|
||||
- /guides/docker-build-cloud/ci/
|
||||
- /guides/docker-build-cloud/common-questions/
|
||||
- /guides/docker-build-cloud/dev/
|
||||
- /guides/docker-build-cloud/why/
|
||||
params:
|
||||
tags: [cicd]
|
||||
image: images/learning-paths/build-cloud.png
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
|
||||
<!-- 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.
|
||||
|
||||
## 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
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
|
||||
## Why Docker Build Cloud?
|
||||
|
||||
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" >}}
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
|
||||
## Demo: set up and use Docker Build Cloud in development
|
||||
|
||||
With Docker Build Cloud, you can easily shift the build workload from local machines
|
||||
to the cloud, helping you achieve faster build times, especially for multi-platform builds.
|
||||
|
||||
In this demo, you'll see:
|
||||
|
||||
- How to setup the builder locally
|
||||
- How to use Docker Build Cloud with Docker Compose
|
||||
- How the image cache speeds up builds for others on your team
|
||||
|
||||
{{< youtube-embed "oPGq2AP5OtQ" >}}
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
|
||||
## Demo: Using Docker Build Cloud in CI
|
||||
|
||||
Docker Build Cloud can significantly decrease the time it takes for your CI builds
|
||||
take to run, saving you time and money.
|
||||
|
||||
Since the builds run remotely, your CI runner can still use the Docker tooling CLI
|
||||
without needing elevated permissions, making your builds more secure by default.
|
||||
|
||||
In this demo, you will see:
|
||||
|
||||
- How to integrate Docker Build Cloud into a variety of CI platforms
|
||||
- How to use Docker Build Cloud in GitHub Actions to build multi-architecture images
|
||||
- Speed differences between a workflow using Docker Build Cloud and a workflow running natively
|
||||
- How to use Docker Build Cloud in a GitLab Pipeline
|
||||
|
||||
{{< youtube-embed "wvLdInoVBGg" >}}
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
|
||||
## Common challenges and questions
|
||||
|
||||
#### 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?
|
||||
|
||||
Pricing details for Docker Build Cloud can be found on the [pricing page](https://www.docker.com/pricing?ref=Docs&refAction=DocsGuidesBuildCloudFaq).
|
||||
|
||||
#### 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 start a trial of Docker Build Cloud. Personal accounts are limited to a
|
||||
single user.
|
||||
|
||||
For teams to receive the shared cache benefit, they must either be on a Docker
|
||||
Team or Docker Business subscription.
|
||||
|
||||
#### 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.
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
title: Why Docker Build Cloud?
|
||||
description: Learn how Docker Build Cloud makes your builds faster.
|
||||
keywords: docker build cloud, cloud builds, shared cache, multi-architecture, build performance
|
||||
weight: 10
|
||||
---
|
||||
|
||||
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" >}}
|
||||
|
||||
<div id="dbc-lp-survey-anchor"></div>
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
title: Defining and running multi-container applications with Docker Compose
|
||||
linkTitle: Docker Compose
|
||||
summary: |
|
||||
Simplify the process of defining, configuring, and running multi-container
|
||||
Docker applications.
|
||||
description: Learn how to use Docker Compose to define and run multi-container Docker applications.
|
||||
keywords: docker compose, multi-container, compose file, services, orchestration, yaml
|
||||
tags: [product-demo]
|
||||
aliases:
|
||||
- /learning-paths/docker-compose/
|
||||
params:
|
||||
image: images/learning-paths/compose.png
|
||||
time: 10 minutes
|
||||
resource_links:
|
||||
- title: Overview of Docker Compose CLI
|
||||
url: /reference/cli/docker/compose/
|
||||
- title: Overview of Docker Compose
|
||||
url: /compose/
|
||||
- title: How Compose works
|
||||
url: /compose/intro/compose-application-model/
|
||||
- title: Using profiles with Compose
|
||||
url: /compose/how-tos/profiles/
|
||||
- title: Control startup and shutdown order with Compose
|
||||
url: /compose/how-tos/startup-order/
|
||||
- title: Compose Build Specification
|
||||
url: /compose/compose-file/build/
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
## What you’ll learn
|
||||
|
||||
- What Docker Compose is and what it does
|
||||
- How to define services
|
||||
- Use cases for Docker Compose
|
||||
- How things would be different without Docker Compose
|
||||
|
||||
## 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.
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
@@ -1,78 +0,0 @@
|
||||
---
|
||||
title: Common challenges and questions
|
||||
description: Explore common challenges and questions related to Docker Compose.
|
||||
keywords: docker compose, faq, troubleshooting, environments, multi-container
|
||||
weight: 30
|
||||
---
|
||||
|
||||
<!-- 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.yaml`). 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/how-tos/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/how-tos/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.yaml` 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.
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
160
content/guides/docker-compose/index.md
Normal file
160
content/guides/docker-compose/index.md
Normal file
@@ -0,0 +1,160 @@
|
||||
---
|
||||
title: Defining and running multi-container applications with Docker Compose
|
||||
linkTitle: Docker Compose
|
||||
summary: |
|
||||
Simplify the process of defining, configuring, and running multi-container
|
||||
Docker applications.
|
||||
description: Learn how to use Docker Compose to define and run multi-container Docker applications.
|
||||
keywords: docker compose, multi-container, compose file, services, orchestration, yaml
|
||||
aliases:
|
||||
- /learning-paths/docker-compose/
|
||||
- /guides/docker-compose/common-questions/
|
||||
- /guides/docker-compose/setup/
|
||||
- /guides/docker-compose/why/
|
||||
params:
|
||||
tags: [cicd]
|
||||
image: images/learning-paths/compose.png
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
|
||||
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.
|
||||
|
||||
## What you’ll learn
|
||||
|
||||
- What Docker Compose is and what it does
|
||||
- How to define services
|
||||
- Use cases for Docker Compose
|
||||
- How things would be different without Docker Compose
|
||||
|
||||
## 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.
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
|
||||
## Why Docker Compose?
|
||||
|
||||
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 >}}
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
|
||||
## Demo: set up and use Docker Compose
|
||||
|
||||
This Docker Compose demo shows how to orchestrate a multi-container application
|
||||
environment, streamlining development and deployment processes.
|
||||
|
||||
- Compare Docker Compose to the `docker run` command
|
||||
- Configure a multi-container web app using a Compose file
|
||||
- Run a multi-container web app using one command
|
||||
|
||||
{{< youtube-embed P5RBKmOLPH4 >}}
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
|
||||
## Common challenges and questions
|
||||
|
||||
<!-- 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.yaml`). 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/how-tos/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/how-tos/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.yaml` 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.
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
title: "Demo: set up and use Docker Compose"
|
||||
description: Learn how to get started with Docker Compose.
|
||||
keywords: docker compose, getting started, multi-container, demo, orchestration
|
||||
weight: 20
|
||||
---
|
||||
|
||||
This Docker Compose demo shows how to orchestrate a multi-container application
|
||||
environment, streamlining development and deployment processes.
|
||||
|
||||
- Compare Docker Compose to the `docker run` command
|
||||
- Configure a multi-container web app using a Compose file
|
||||
- Run a multi-container web app using one command
|
||||
|
||||
{{< youtube-embed P5RBKmOLPH4 >}}
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Why Docker Compose?
|
||||
description: Learn how Docker Compose can help you simplify app development.
|
||||
keywords: docker compose, multi-container, yaml, services, orchestration, application
|
||||
weight: 10
|
||||
---
|
||||
|
||||
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 >}}
|
||||
|
||||
<div id="compose-lp-survey-anchor"></div>
|
||||
@@ -1,65 +0,0 @@
|
||||
---
|
||||
title: Securing your software supply chain with Docker Scout
|
||||
linkTitle: Docker Scout
|
||||
summary: |
|
||||
Enhance container security by automating vulnerability detection and
|
||||
remediation.
|
||||
description: |
|
||||
Learn how to use Docker Scout to enhance container security by automating
|
||||
vulnerability detection and remediation, ensuring compliance, and protecting
|
||||
your development workflow.
|
||||
keywords: docker scout, container security, vulnerability scanning, sbom, supply chain, remediation
|
||||
tags: [product-demo]
|
||||
aliases:
|
||||
- /learning-paths/docker-scout/
|
||||
params:
|
||||
image: images/learning-paths/scout.png
|
||||
time: 20 minutes
|
||||
resource_links:
|
||||
- title: Docker Scout overview
|
||||
url: /scout/
|
||||
- title: Docker Scout quickstart
|
||||
url: /scout/quickstart/
|
||||
- title: Install Docker Scout
|
||||
url: /scout/install/
|
||||
---
|
||||
|
||||
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
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: Attestations
|
||||
keywords: build, attestations, sbom, provenance, metadata
|
||||
description: |
|
||||
Introduction to SBOM and provenance attestations with Docker Build,
|
||||
what they are, and why they exist
|
||||
weight: 50
|
||||
---
|
||||
|
||||
{{< youtube-embed qOzcycbTs4o >}}
|
||||
|
||||
[Build attestations](/manuals/build/metadata/attestations/_index.md) give you
|
||||
detailed information about how an image was built and what it contains. These
|
||||
attestations, generated by BuildKit during build-time, attach to the final
|
||||
image as metadata, allowing you to inspect an image to see its origin, creator,
|
||||
and contents. This information helps you make informed decisions about the
|
||||
security and impact of the image on your supply chain.
|
||||
|
||||
Docker Scout uses these attestations to evaluate the image's security and
|
||||
supply chain posture, and to provide remediation recommendations for issues. If
|
||||
issues are detected, such as missing or outdated attestations, Docker Scout can
|
||||
guide you on how to add or update them, ensuring compliance and improving
|
||||
visibility into the image's security status.
|
||||
|
||||
There are two key types of attestations:
|
||||
|
||||
- SBOM, which lists the software artifacts within the image.
|
||||
- Provenance, which details how the image was built.
|
||||
|
||||
You can create attestations by using `docker buildx build` with the
|
||||
`--provenance` and `--sbom` flags. Attestations attach to the image index,
|
||||
allowing you to inspect them without pulling the entire image. Docker Scout
|
||||
leverages this metadata to give you more precise recommendations and better
|
||||
control over your image's security.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,61 +0,0 @@
|
||||
---
|
||||
title: Common challenges and questions
|
||||
description: Explore common challenges and questions related to Docker Scout.
|
||||
keywords: docker scout, faq, container security, vulnerability scanning, troubleshooting
|
||||
---
|
||||
|
||||
<!-- 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.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Docker Scout demo
|
||||
linkTitle: Demo
|
||||
description: Learn about Docker Scout's powerful features for enhanced supply chain security.
|
||||
keywords: docker scout, demo, supply chain, vulnerability scanning, container security
|
||||
weight: 20
|
||||
---
|
||||
|
||||
{{< youtube-embed "TkLwJ0p46W8" >}}
|
||||
|
||||
Docker Scout has powerful features for enhancing containerized application
|
||||
security and ensuring a robust software supply chain.
|
||||
|
||||
- Define vulnerability remediation
|
||||
- Discuss why remediation is essential to maintain the security and integrity
|
||||
of containerized applications
|
||||
- Discuss common vulnerabilities
|
||||
- Implement remediation techniques: updating base images, applying patches,
|
||||
removing unnecessary packages
|
||||
- Verify and validate remediation efforts using Docker Scout
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
325
content/guides/docker-scout/index.md
Normal file
325
content/guides/docker-scout/index.md
Normal file
@@ -0,0 +1,325 @@
|
||||
---
|
||||
title: Securing your software supply chain with Docker Scout
|
||||
linkTitle: Docker Scout
|
||||
summary: |
|
||||
Enhance container security by automating vulnerability detection and
|
||||
remediation.
|
||||
description: |
|
||||
Learn how to use Docker Scout to enhance container security by automating
|
||||
vulnerability detection and remediation, ensuring compliance, and protecting
|
||||
your development workflow.
|
||||
keywords: docker scout, container security, vulnerability scanning, sbom, supply chain, remediation
|
||||
aliases:
|
||||
- /learning-paths/docker-scout/
|
||||
- /scout/concepts/s3c/
|
||||
- /scout/concepts/sbom/
|
||||
- /guides/docker-scout/attestations/
|
||||
- /guides/docker-scout/common-questions/
|
||||
- /guides/docker-scout/demo/
|
||||
- /guides/docker-scout/remediation/
|
||||
- /guides/docker-scout/s3c/
|
||||
- /guides/docker-scout/sbom/
|
||||
- /guides/docker-scout/why/
|
||||
params:
|
||||
tags: [security]
|
||||
image: images/learning-paths/scout.png
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
|
||||
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
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
|
||||
## Why Docker Scout?
|
||||
|
||||
{{< youtube-embed "-omsQ7Uqyc4" >}}
|
||||
|
||||
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 Software Development Lifecycle (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.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
|
||||
## Docker Scout demo
|
||||
|
||||
{{< youtube-embed "TkLwJ0p46W8" >}}
|
||||
|
||||
Docker Scout has powerful features for enhancing containerized application
|
||||
security and ensuring a robust software supply chain.
|
||||
|
||||
- Define vulnerability remediation
|
||||
- Discuss why remediation is essential to maintain the security and integrity
|
||||
of containerized applications
|
||||
- Discuss common vulnerabilities
|
||||
- Implement remediation techniques: updating base images, applying patches,
|
||||
removing unnecessary packages
|
||||
- Verify and validate remediation efforts using Docker Scout
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
|
||||
## Software supply chain security
|
||||
|
||||
{{< youtube-embed YzNK6E7APv0 >}}
|
||||
|
||||
The term "software supply chain" refers to the end-to-end process of developing
|
||||
and delivering software, from the development to deployment and maintenance.
|
||||
Software supply chain security, or "S3C" for short, is the practice for
|
||||
protecting the components and processes of the supply chain.
|
||||
|
||||
S3C is a fundamental change in how organizations approach software security.
|
||||
Traditionally in the software industry, security and compliance has been mostly
|
||||
an afterthought, left to the software delivery or release phase. With S3C,
|
||||
security is integrated into the entire software development lifecycle, from the
|
||||
inner loop of development and testing, to the outer loop of shipping and
|
||||
monitoring.
|
||||
|
||||
Following industry best practices for software supply chain conduct is
|
||||
important because it helps organizations protect their software from security
|
||||
threats, compliance risks, and other vulnerabilities. Implementing a software
|
||||
supply chain security framework improves visibility, collaboration, and
|
||||
traceability of a project across stakeholders. This helps organizations detect,
|
||||
respond to, and remediate threats more effectively.
|
||||
|
||||
### Securing the software supply chain
|
||||
|
||||
Building a secure software supply chain involves several key steps, such as:
|
||||
|
||||
- Identify the software components and dependencies you use to build and run
|
||||
your applications.
|
||||
- Automate security testing throughout the software development lifecycle.
|
||||
- Monitor your software supply chain for security threats.
|
||||
- Implement security policies that govern how software is built, and the
|
||||
components it contains.
|
||||
|
||||
Managing the software supply chain is a complex task, especially in the modern
|
||||
day where software is built using multiple components from different sources.
|
||||
Organizations need to have a clear understanding of the software components
|
||||
they use, and the security risks associated with them.
|
||||
|
||||
### How Docker Scout is different
|
||||
|
||||
Docker Scout is a platform designed to help organizations secure their software
|
||||
supply chain. It provides tools and services for identifying and managing
|
||||
software assets and policies, and automated remediation of security threats.
|
||||
|
||||
Unlike traditional security tools that focus on scheduled, point-in-time scans
|
||||
at specific stages in the software development lifecycle, Docker Scout uses a
|
||||
modern event-driven model that spans the entire software supply chain. This
|
||||
means that when a new vulnerability affecting your images is disclosed, your
|
||||
updated risk assessment is available within seconds, and earlier in the
|
||||
development process.
|
||||
|
||||
Docker Scout works by analyzing the composition of your images to create a
|
||||
Software Bill of Materials (SBOM). The SBOM is cross-referenced against the
|
||||
security advisories to identify CVEs that affect your images. Docker Scout
|
||||
integrates with [over 20 different security
|
||||
advisories](/manuals/scout/deep-dive/advisory-db-sources.md), and updates its
|
||||
vulnerability database in real-time. This ensures that your security posture is
|
||||
represented using the latest available information.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
|
||||
## Software Bill of Materials
|
||||
|
||||
{{< youtube-embed PbS4y7C7h4A >}}
|
||||
|
||||
A Bill of Materials (BOM) is a list of materials, parts, and the quantities of
|
||||
each needed to manufacture a product. For example, a BOM for a computer might
|
||||
list the motherboard, CPU, RAM, power supply, storage devices, case, and other
|
||||
components, along with the quantities of each that are needed to build the
|
||||
computer.
|
||||
|
||||
A Software Bill of Materials (SBOM) is a list of all the components that make
|
||||
up a piece of software. This includes open source and third-party components,
|
||||
as well as any custom code that has been written for the software. An SBOM is
|
||||
similar to a BOM for a physical product, but for software.
|
||||
|
||||
In the context of software supply chain security, SBOMs can help with
|
||||
identifying and mitigating security and compliance risks in software. By
|
||||
knowing exactly what components are used in a piece of software, you can
|
||||
quickly identify and patch vulnerabilities in your components, or determine if
|
||||
a component is licensed in a way that is incompatible with your project.
|
||||
|
||||
### Contents of an SBOM
|
||||
|
||||
An SBOM typically includes the following information:
|
||||
|
||||
- The name of the software, such as the name of a library or framework, that
|
||||
the SBOM describes.
|
||||
- The version of the software.
|
||||
- The license under which the software is distributed.
|
||||
- A list of other components that the software depends on.
|
||||
|
||||
### How Docker Scout uses SBOMs
|
||||
|
||||
Docker Scout uses SBOMs 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 it will generate an SBOM on the fly
|
||||
by analyzing the contents of the image.
|
||||
|
||||
The SBOM is cross-referenced with the [advisory database](/manuals/scout/deep-dive/advisory-db-sources.md)
|
||||
to determine if any of the components in the image have known vulnerabilities.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
|
||||
## Attestations
|
||||
|
||||
{{< youtube-embed qOzcycbTs4o >}}
|
||||
|
||||
[Build attestations](/manuals/build/metadata/attestations/_index.md) give you
|
||||
detailed information about how an image was built and what it contains. These
|
||||
attestations, generated by BuildKit during build-time, attach to the final
|
||||
image as metadata, allowing you to inspect an image to see its origin, creator,
|
||||
and contents. This information helps you make informed decisions about the
|
||||
security and impact of the image on your supply chain.
|
||||
|
||||
Docker Scout uses these attestations to evaluate the image's security and
|
||||
supply chain posture, and to provide remediation recommendations for issues. If
|
||||
issues are detected, such as missing or outdated attestations, Docker Scout can
|
||||
guide you on how to add or update them, ensuring compliance and improving
|
||||
visibility into the image's security status.
|
||||
|
||||
There are two key types of attestations:
|
||||
|
||||
- SBOM, which lists the software artifacts within the image.
|
||||
- Provenance, which details how the image was built.
|
||||
|
||||
You can create attestations by using `docker buildx build` with the
|
||||
`--provenance` and `--sbom` flags. Attestations attach to the image index,
|
||||
allowing you to inspect them without pulling the entire image. Docker Scout
|
||||
leverages this metadata to give you more precise recommendations and better
|
||||
control over your image's security.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
|
||||
## Remediation
|
||||
|
||||
{{< youtube-embed jM9zLBf8M-8 >}}
|
||||
|
||||
Docker Scout's [remediation feature](/manuals/scout/policy/remediation.md)
|
||||
helps you address supply chain and security issues by offering tailored
|
||||
recommendations based on policy evaluations. These recommendations guide you in
|
||||
improving policy compliance or enhancing image metadata, allowing Docker Scout
|
||||
to perform more accurate evaluations in the future.
|
||||
|
||||
You can use this feature to ensure that your base images are up-to-date and
|
||||
that your supply chain attestations are complete. When a violation occurs,
|
||||
Docker Scout provides recommended fixes, such as updating your base image or
|
||||
adding missing attestations. If there isn’t enough information to determine
|
||||
compliance, Docker Scout suggests actions to help resolve the issue.
|
||||
|
||||
In the Docker Scout Dashboard, you can view and act on these recommendations by
|
||||
reviewing violations or compliance uncertainties. With integrations like
|
||||
GitHub, you can even automate updates, directly fixing issues from the
|
||||
dashboard.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
|
||||
## Common challenges and questions
|
||||
|
||||
<!-- 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.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
title: Remediation
|
||||
description: Learn how Docker Scout can help you improve your software quality automatically, using remediation
|
||||
keywords: scout, supply chain, security, remediation, automation
|
||||
weight: 60
|
||||
---
|
||||
|
||||
{{< youtube-embed jM9zLBf8M-8 >}}
|
||||
|
||||
Docker Scout's [remediation feature](/manuals/scout/policy/remediation.md)
|
||||
helps you address supply chain and security issues by offering tailored
|
||||
recommendations based on policy evaluations. These recommendations guide you in
|
||||
improving policy compliance or enhancing image metadata, allowing Docker Scout
|
||||
to perform more accurate evaluations in the future.
|
||||
|
||||
You can use this feature to ensure that your base images are up-to-date and
|
||||
that your supply chain attestations are complete. When a violation occurs,
|
||||
Docker Scout provides recommended fixes, such as updating your base image or
|
||||
adding missing attestations. If there isn’t enough information to determine
|
||||
compliance, Docker Scout suggests actions to help resolve the issue.
|
||||
|
||||
In the Docker Scout Dashboard, you can view and act on these recommendations by
|
||||
reviewing violations or compliance uncertainties. With integrations like
|
||||
GitHub, you can even automate updates, directly fixing issues from the
|
||||
dashboard.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
title: Software supply chain security
|
||||
description: Learn about software supply chain security (S3C), what it means, and why it is important.
|
||||
keywords: docker scout, secure, software, supply, chain, security, sssc, sscs, s3c
|
||||
aliases:
|
||||
- /scout/concepts/s3c/
|
||||
weight: 30
|
||||
---
|
||||
|
||||
{{< youtube-embed YzNK6E7APv0 >}}
|
||||
|
||||
The term "software supply chain" refers to the end-to-end process of developing
|
||||
and delivering software, from the development to deployment and maintenance.
|
||||
Software supply chain security, or "S3C" for short, is the practice for
|
||||
protecting the components and processes of the supply chain.
|
||||
|
||||
S3C is a fundamental change in how organizations approach software security.
|
||||
Traditionally in the software industry, security and compliance has been mostly
|
||||
an afterthought, left to the software delivery or release phase. With S3C,
|
||||
security is integrated into the entire software development lifecycle, from the
|
||||
inner loop of development and testing, to the outer loop of shipping and
|
||||
monitoring.
|
||||
|
||||
Following industry best practices for software supply chain conduct is
|
||||
important because it helps organizations protect their software from security
|
||||
threats, compliance risks, and other vulnerabilities. Implementing a software
|
||||
supply chain security framework improves visibility, collaboration, and
|
||||
traceability of a project across stakeholders. This helps organizations detect,
|
||||
respond to, and remediate threats more effectively.
|
||||
|
||||
## Securing the software supply chain
|
||||
|
||||
Building a secure software supply chain involves several key steps, such as:
|
||||
|
||||
- Identify the software components and dependencies you use to build and run
|
||||
your applications.
|
||||
- Automate security testing throughout the software development lifecycle.
|
||||
- Monitor your software supply chain for security threats.
|
||||
- Implement security policies that govern how software is built, and the
|
||||
components it contains.
|
||||
|
||||
Managing the software supply chain is a complex task, especially in the modern
|
||||
day where software is built using multiple components from different sources.
|
||||
Organizations need to have a clear understanding of the software components
|
||||
they use, and the security risks associated with them.
|
||||
|
||||
## How Docker Scout is different
|
||||
|
||||
Docker Scout is a platform designed to help organizations secure their software
|
||||
supply chain. It provides tools and services for identifying and managing
|
||||
software assets and policies, and automated remediation of security threats.
|
||||
|
||||
Unlike traditional security tools that focus on scheduled, point-in-time scans
|
||||
at specific stages in the software development lifecycle, Docker Scout uses a
|
||||
modern event-driven model that spans the entire software supply chain. This
|
||||
means that when a new vulnerability affecting your images is disclosed, your
|
||||
updated risk assessment is available within seconds, and earlier in the
|
||||
development process.
|
||||
|
||||
Docker Scout works by analyzing the composition of your images to create a
|
||||
Software Bill of Materials (SBOM). The SBOM is cross-referenced against the
|
||||
security advisories to identify CVEs that affect your images. Docker Scout
|
||||
integrates with [over 20 different security
|
||||
advisories](/manuals/scout/deep-dive/advisory-db-sources.md), and updates its
|
||||
vulnerability database in real-time. This ensures that your security posture is
|
||||
represented using the latest available information.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
title: Software Bill of Materials
|
||||
description: Learn about Software Bill of Materials (SBOM) and how Docker Scout uses it.
|
||||
keywords: scout, sbom, software bill of materials, analysis, composition
|
||||
aliases:
|
||||
- /scout/concepts/sbom/
|
||||
weight: 40
|
||||
---
|
||||
|
||||
{{< youtube-embed PbS4y7C7h4A >}}
|
||||
|
||||
A Bill of Materials (BOM) is a list of materials, parts, and the quantities of
|
||||
each needed to manufacture a product. For example, a BOM for a computer might
|
||||
list the motherboard, CPU, RAM, power supply, storage devices, case, and other
|
||||
components, along with the quantities of each that are needed to build the
|
||||
computer.
|
||||
|
||||
A Software Bill of Materials (SBOM) is a list of all the components that make
|
||||
up a piece of software. This includes open source and third-party components,
|
||||
as well as any custom code that has been written for the software. An SBOM is
|
||||
similar to a BOM for a physical product, but for software.
|
||||
|
||||
In the context of software supply chain security, SBOMs can help with
|
||||
identifying and mitigating security and compliance risks in software. By
|
||||
knowing exactly what components are used in a piece of software, you can
|
||||
quickly identify and patch vulnerabilities in your components, or determine if
|
||||
a component is licensed in a way that is incompatible with your project.
|
||||
|
||||
## Contents of an SBOM
|
||||
|
||||
An SBOM typically includes the following information:
|
||||
|
||||
- The name of the software, such as the name of a library or framework, that
|
||||
the SBOM describes.
|
||||
- The version of the software.
|
||||
- The license under which the software is distributed.
|
||||
- A list of other components that the software depends on.
|
||||
|
||||
## How Docker Scout uses SBOMs
|
||||
|
||||
Docker Scout uses SBOMs 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 it will generate an SBOM on the fly
|
||||
by analyzing the contents of the image.
|
||||
|
||||
The SBOM is cross-referenced with the [advisory database](/manuals/scout/deep-dive/advisory-db-sources.md)
|
||||
to determine if any of the components in the image have known vulnerabilities.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
title: Why Docker Scout?
|
||||
description: Learn how Docker Scout can help you secure your supply chain.
|
||||
keywords: docker scout, supply chain security, vulnerability detection, sbom, container security
|
||||
weight: 10
|
||||
---
|
||||
|
||||
{{< youtube-embed "-omsQ7Uqyc4" >}}
|
||||
|
||||
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 Software Development Lifecycle (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.
|
||||
|
||||
<div id="scout-lp-survey-anchor"></div>
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
title: .NET language-specific guide
|
||||
linkTitle: C# (.NET)
|
||||
description: Containerize and develop .NET apps using Docker
|
||||
summary: |
|
||||
Learn how to containerize .NET applications using Docker.
|
||||
keywords: getting started, .net
|
||||
aliases:
|
||||
- /language/dotnet/
|
||||
- /guides/language/dotnet/
|
||||
- /guides/dotnet/configure-ci-cd/
|
||||
- /language/dotnet/configure-ci-cd/
|
||||
- /guides/language/dotnet/configure-ci-cd/
|
||||
- /guides/dotnet/deploy/
|
||||
- /language/dotnet/deploy/
|
||||
- /guides/language/dotnet/deploy/
|
||||
languages: [c-sharp]
|
||||
params:
|
||||
time: 20 minutes
|
||||
toc_min: 1
|
||||
toc_max: 2
|
||||
---
|
||||
|
||||
The .NET getting started guide teaches you how to create a containerized .NET application using Docker. In this guide, you'll learn how to:
|
||||
|
||||
- Containerize and run a .NET application
|
||||
- Set up a local environment to develop a .NET application using containers
|
||||
- Run tests for a .NET application using containers
|
||||
|
||||
After completing the .NET getting started modules, you should be able to containerize your own .NET application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing .NET application.
|
||||
@@ -1,364 +0,0 @@
|
||||
---
|
||||
title: Containerize a .NET application
|
||||
linkTitle: Containerize your app
|
||||
weight: 10
|
||||
keywords: .net, containerize, initialize
|
||||
description: Learn how to containerize an ASP.NET application.
|
||||
aliases:
|
||||
- /language/dotnet/build-images/
|
||||
- /language/dotnet/run-containers/
|
||||
- /language/dotnet/containerize/
|
||||
- /guides/language/dotnet/containerize/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* You have installed the latest version of [Docker
|
||||
Desktop](/get-started/get-docker.md).
|
||||
* You have a [git client](https://git-scm.com/downloads). The examples in this
|
||||
section use a command-line based git client, but you can use any client.
|
||||
|
||||
## Overview
|
||||
|
||||
This section walks you through containerizing and running a .NET
|
||||
application.
|
||||
|
||||
## Get the sample applications
|
||||
|
||||
In this guide, you will use a pre-built .NET application. The application is
|
||||
similar to the application built in the Docker Blog article, [Building a
|
||||
Multi-Container .NET App Using Docker
|
||||
Desktop](https://www.docker.com/blog/building-multi-container-net-app-using-docker-desktop/).
|
||||
|
||||
Open a terminal, change directory to a directory that you want to work in, and
|
||||
run the following command to clone the repository.
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/docker/docker-dotnet-sample
|
||||
```
|
||||
|
||||
## Create Docker assets
|
||||
|
||||
Now that you have an application, you can create the necessary Docker assets to containerize it. You can choose between using the official .NET images or Docker Hardened Images (DHI).
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> [Gordon](/ai/gordon/), Docker's AI assistant, can generate Docker assets for your project. Ask Gordon to create a Dockerfile, Compose file, and `.dockerignore` tailored to your application.
|
||||
|
||||
> [Docker Hardened Images (DHIs)](https://docs.docker.com/dhi/) are minimal, secure, and production-ready container base and application images maintained by Docker. DHI images are recommended for better security—they are designed to reduce vulnerabilities and simplify compliance.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Using Docker Hardened Images" >}}
|
||||
|
||||
Docker Hardened Images (DHIs) for .NET are available in the [Docker Hardened Images catalog](https://hub.docker.com/hardened-images/catalog/dhi/aspnetcore). Docker Hardened Images are freely available to everyone with no subscription required. You can pull and use them like any other Docker image after signing in to the DHI registry. For more information, see the [DHI quickstart](/dhi/get-started/) guide.
|
||||
|
||||
1. Sign in to the DHI registry:
|
||||
```console
|
||||
$ docker login dhi.io
|
||||
```
|
||||
|
||||
2. Pull the .NET SDK DHI (check the catalog for available versions):
|
||||
```console
|
||||
$ docker pull dhi.io/dotnet:10-sdk
|
||||
```
|
||||
|
||||
3. Pull the ASP.NET Core runtime DHI (check the catalog for available versions):
|
||||
```console
|
||||
$ docker pull dhi.io/aspnetcore:10
|
||||
```
|
||||
|
||||
Create the following files in your `docker-dotnet-sample` directory.
|
||||
|
||||
```dockerfile {collapse=true,title=Dockerfile}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM dhi.io/aspnetcore:10 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> DHI runtime images already run as a non-root user (`nonroot`, UID 65532), so there's no need to create a user or specify `USER` in your Dockerfile. This reduces the attack surface and simplifies your configuration.
|
||||
|
||||
```yaml {collapse=true,title=compose.yaml}
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Docker Compose reference guide at
|
||||
# https://docs.docker.com/go/compose-spec-reference/
|
||||
|
||||
# Here the instructions define your application as a service called "server".
|
||||
# This service is built from the Dockerfile in the current directory.
|
||||
# You can add other services your application may depend on here, such as a
|
||||
# database or a cache. For examples, see the Awesome Compose repository:
|
||||
# https://github.com/docker/awesome-compose
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
||||
# The commented out section below is an example of how to define a PostgreSQL
|
||||
# database that your application can use. `depends_on` tells Docker Compose to
|
||||
# start the database before your application. The `db-data` volume persists the
|
||||
# database data between container restarts. The `db-password` secret is used
|
||||
# to set the database password. You must create `db/password.txt` and add
|
||||
# a password of your choosing to it before running `docker compose up`.
|
||||
# depends_on:
|
||||
# db:
|
||||
# condition: service_healthy
|
||||
# db:
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# user: postgres
|
||||
# secrets:
|
||||
# - db-password
|
||||
# volumes:
|
||||
# - db-data:/var/lib/postgresql/data
|
||||
# environment:
|
||||
# - POSTGRES_DB=example
|
||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
# expose:
|
||||
# - 5432
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "pg_isready" ]
|
||||
# interval: 10s
|
||||
# timeout: 5s
|
||||
# retries: 5
|
||||
# volumes:
|
||||
# db-data:
|
||||
# secrets:
|
||||
# db-password:
|
||||
# file: db/password.txt
|
||||
```
|
||||
|
||||
```text {collapse=true,title=".dockerignore"}
|
||||
# Include any files or directories that you don't want to be copied to your
|
||||
# container here (e.g., local build artifacts, temporary files, etc.).
|
||||
#
|
||||
# For more help, visit the .dockerignore file reference guide at
|
||||
# https://docs.docker.com/go/build-context-dockerignore/
|
||||
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/compose.y*ml
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Using the official .NET 10 image" >}}
|
||||
|
||||
Create the following files in your `docker-dotnet-sample` directory.
|
||||
|
||||
```dockerfile {collapse=true,title=Dockerfile}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
USER appuser
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
```yaml {collapse=true,title=compose.yaml}
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Docker Compose reference guide at
|
||||
# https://docs.docker.com/go/compose-spec-reference/
|
||||
|
||||
# Here the instructions define your application as a service called "server".
|
||||
# This service is built from the Dockerfile in the current directory.
|
||||
# You can add other services your application may depend on here, such as a
|
||||
# database or a cache. For examples, see the Awesome Compose repository:
|
||||
# https://github.com/docker/awesome-compose
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
||||
# The commented out section below is an example of how to define a PostgreSQL
|
||||
# database that your application can use. `depends_on` tells Docker Compose to
|
||||
# start the database before your application. The `db-data` volume persists the
|
||||
# database data between container restarts. The `db-password` secret is used
|
||||
# to set the database password. You must create `db/password.txt` and add
|
||||
# a password of your choosing to it before running `docker compose up`.
|
||||
# depends_on:
|
||||
# db:
|
||||
# condition: service_healthy
|
||||
# db:
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# user: postgres
|
||||
# secrets:
|
||||
# - db-password
|
||||
# volumes:
|
||||
# - db-data:/var/lib/postgresql/data
|
||||
# environment:
|
||||
# - POSTGRES_DB=example
|
||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
# expose:
|
||||
# - 5432
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "pg_isready" ]
|
||||
# interval: 10s
|
||||
# timeout: 5s
|
||||
# retries: 5
|
||||
# volumes:
|
||||
# db-data:
|
||||
# secrets:
|
||||
# db-password:
|
||||
# file: db/password.txt
|
||||
```
|
||||
|
||||
```text {collapse=true,title=".dockerignore"}
|
||||
# Include any files or directories that you don't want to be copied to your
|
||||
# container here (e.g., local build artifacts, temporary files, etc.).
|
||||
#
|
||||
# For more help, visit the .dockerignore file reference guide at
|
||||
# https://docs.docker.com/go/build-context-dockerignore/
|
||||
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/compose.y*ml
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
You should now have the following contents in your `docker-dotnet-sample`
|
||||
directory.
|
||||
|
||||
```text
|
||||
├── docker-dotnet-sample/
|
||||
│ ├── .git/
|
||||
│ ├── src/
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── Dockerfile
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
To learn more about the files, see the following:
|
||||
- [Dockerfile](/reference/dockerfile.md)
|
||||
- [.dockerignore](/reference/dockerfile.md#dockerignore-file)
|
||||
- [compose.yaml](/reference/compose-file/_index.md)
|
||||
|
||||
## Run the application
|
||||
|
||||
Inside the `docker-dotnet-sample` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application.
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `docker-dotnet-sample` directory, run the following command
|
||||
in a terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build -d
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application.
|
||||
|
||||
In the terminal, run the following command to stop the application.
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
For more information about Compose commands, see the [Compose CLI
|
||||
reference](/reference/cli/docker/compose/).
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how you can containerize and run your .NET
|
||||
application using Docker.
|
||||
|
||||
Related information:
|
||||
- [Dockerfile reference](/reference/dockerfile.md)
|
||||
- [.dockerignore file reference](/reference/dockerfile.md#dockerignore-file)
|
||||
- [Docker Compose overview](/manuals/compose/_index.md)
|
||||
- [Docker Hardened Images](/dhi/)
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how you can develop your application using
|
||||
Docker containers.
|
||||
@@ -1,425 +0,0 @@
|
||||
---
|
||||
title: Use containers for .NET development
|
||||
linkTitle: Develop your app
|
||||
weight: 20
|
||||
keywords: .net, development
|
||||
description: Learn how to develop your .NET application locally using containers.
|
||||
aliases:
|
||||
- /language/dotnet/develop/
|
||||
- /guides/language/dotnet/develop/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Containerize a .NET application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Adding a local database and persisting data
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
- Creating a development container that contains the .NET Core SDK tools and dependencies
|
||||
|
||||
## Update the application
|
||||
|
||||
This section uses a different branch of the `docker-dotnet-sample` repository
|
||||
that contains an updated .NET application. The updated application is on the
|
||||
`add-db` branch of the repository you cloned in [Containerize a .NET
|
||||
application](containerize.md).
|
||||
|
||||
To get the updated code, you need to checkout the `add-db` branch. For the changes you made in [Containerize a .NET application](containerize.md), for this section, you can stash them. In a terminal, run the following commands in the `docker-dotnet-sample` directory.
|
||||
|
||||
1. Stash any previous changes.
|
||||
|
||||
```console
|
||||
$ git stash -u
|
||||
```
|
||||
|
||||
2. Check out the new branch with the updated application.
|
||||
|
||||
```console
|
||||
$ git checkout add-db
|
||||
```
|
||||
|
||||
In the `add-db` branch, only the .NET application has been updated. None of the Docker assets have been updated yet.
|
||||
|
||||
You should now have the following in your `docker-dotnet-sample` directory.
|
||||
|
||||
```text
|
||||
├── docker-dotnet-sample/
|
||||
│ ├── .git/
|
||||
│ ├── src/
|
||||
│ │ ├── Data/
|
||||
│ │ ├── Models/
|
||||
│ │ ├── Pages/
|
||||
│ │ ├── Properties/
|
||||
│ │ ├── wwwroot/
|
||||
│ │ ├── appsettings.Development.json
|
||||
│ │ ├── appsettings.json
|
||||
│ │ ├── myWebApp.csproj
|
||||
│ │ └── Program.cs
|
||||
│ ├── tests/
|
||||
│ │ ├── tests.csproj
|
||||
│ │ ├── UnitTest1.cs
|
||||
│ │ └── Usings.cs
|
||||
│ ├── .dockerignore
|
||||
│ ├── .gitignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── Dockerfile
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
## Add a local database and persist data
|
||||
|
||||
You can use containers to set up local services, like a database. In this section, you'll update the `compose.yaml` file to define a database service and a volume to persist data.
|
||||
|
||||
Open the `compose.yaml` file in an IDE or text editor. You'll notice it
|
||||
already contains commented-out instructions for a PostgreSQL database and volume.
|
||||
|
||||
Open `docker-dotnet-sample/src/appsettings.json` in an IDE or text editor. You'll
|
||||
notice the connection string with all the database information. The
|
||||
`compose.yaml` already contains this information, but it's commented out.
|
||||
Uncomment the database instructions in the `compose.yaml` file.
|
||||
|
||||
The following is the updated `compose.yaml` file.
|
||||
|
||||
```yaml {hl_lines="8-33"}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
db:
|
||||
image: postgres:18
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> To learn more about the instructions in the Compose file, see [Compose file
|
||||
> reference](/reference/compose-file/).
|
||||
|
||||
Before you run the application using Compose, notice that this Compose file uses
|
||||
`secrets` and specifies a `password.txt` file to hold the database's password.
|
||||
You must create this file as it's not included in the source repository.
|
||||
|
||||
In the `docker-dotnet-sample` directory, create a new directory named `db` and
|
||||
inside that directory create a file named `password.txt`. Open `password.txt` in an IDE or text editor and add the following password. The password must be on a single line, with no additional lines in the file.
|
||||
|
||||
```text
|
||||
example
|
||||
```
|
||||
|
||||
Save and close the `password.txt` file.
|
||||
|
||||
You should now have the following in your `docker-dotnet-sample` directory.
|
||||
|
||||
```text
|
||||
├── docker-dotnet-sample/
|
||||
│ ├── .git/
|
||||
│ ├── db/
|
||||
│ │ └── password.txt
|
||||
│ ├── src/
|
||||
│ ├── tests/
|
||||
│ ├── .dockerignore
|
||||
│ ├── .gitignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── Dockerfile
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
Run the following command to start your application.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application with the text `Student name is`.
|
||||
|
||||
The application doesn't display a name because the database is empty. For this application, you need to access the database and then add records.
|
||||
|
||||
## Add records to the database
|
||||
|
||||
For the sample application, you must access the database directly to create sample records.
|
||||
|
||||
You can run commands inside the database container using the `docker exec`
|
||||
command. Before running that command, you must get the ID of the database
|
||||
container. Open a new terminal window and run the following command to list all
|
||||
your running containers.
|
||||
|
||||
```console
|
||||
$ docker container ls
|
||||
```
|
||||
|
||||
You should see output like the following.
|
||||
|
||||
```console
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
cb36e310aa7e docker-dotnet-sample-server "dotnet myWebApp.dll" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp docker-dotnet-sample-server-1
|
||||
39fdcf0aff7b postgres:18 "docker-entrypoint.s…" About a minute ago Up About a minute (healthy) 5432/tcp docker-dotnet-sample-db-1
|
||||
```
|
||||
|
||||
In the previous example, the container ID is `39fdcf0aff7b`. Run the following command to connect to the postgres database in the container. Replace the container ID with your own container ID.
|
||||
|
||||
```console
|
||||
$ docker exec -it 39fdcf0aff7b psql -d example -U postgres
|
||||
```
|
||||
|
||||
And finally, insert a record into the database.
|
||||
|
||||
```console
|
||||
example=# INSERT INTO "Students" ("ID", "LastName", "FirstMidName", "EnrollmentDate") VALUES (DEFAULT, 'Whale', 'Moby', '2013-03-20');
|
||||
```
|
||||
|
||||
You should see output like the following.
|
||||
|
||||
```console
|
||||
INSERT 0 1
|
||||
```
|
||||
|
||||
Close the database connection and exit the container shell by running `exit`.
|
||||
|
||||
```console
|
||||
example=# exit
|
||||
```
|
||||
|
||||
## Verify that data persists in the database
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application with the text `Student name is Moby Whale`.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
In the terminal, run `docker compose rm` to remove your containers and then run `docker compose up` to run your application again.
|
||||
|
||||
```console
|
||||
$ docker compose rm
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Refresh [http://localhost:8080](http://localhost:8080) in your browser and verify that the student name persisted, even after the containers were removed and ran again.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
## Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you edit and save your code. For more details about Compose Watch, see [Use Compose Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yaml` file in an IDE or text editor and then add the Compose Watch instructions. The following is the updated `compose.yaml` file.
|
||||
|
||||
```yaml {hl_lines="11-14"}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
db:
|
||||
image: postgres:18
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Open a browser and verify that the application is running at [http://localhost:8080](http://localhost:8080).
|
||||
|
||||
Any changes to the application's source files on your local machine will now be
|
||||
immediately reflected in the running container.
|
||||
|
||||
Open `docker-dotnet-sample/src/Pages/Index.cshtml` in an IDE or text editor and update the student name text on line 13 from `Student name is` to `Student name:`.
|
||||
|
||||
```diff
|
||||
- <p>Student name is @Model.StudentName</p>
|
||||
+ <p>Student name: @Model.StudentName</p>
|
||||
```
|
||||
|
||||
Save the changes to `Index.cshtml` and then wait a few seconds for the application to rebuild. Refresh [http://localhost:8080](http://localhost:8080) in your browser and verify that the updated text appears.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
## Create a development container
|
||||
|
||||
At this point, when you run your containerized application, it's using the .NET runtime image. While this small image is good for production, it lacks the SDK tools and dependencies you may need when developing. Also, during development, you may not need to run `dotnet publish`. You can use multi-stage builds to build stages for both development and production in the same Dockerfile. For more details, see [Multi-stage builds](/manuals/build/building/multi-stage.md).
|
||||
|
||||
Add a new development stage to your Dockerfile and update your `compose.yaml` file to use this stage for local development.
|
||||
|
||||
The following is the updated Dockerfile.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Using Docker Hardened Images" >}}
|
||||
|
||||
```Dockerfile {hl_lines="10-13"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM dhi.io/dotnet:10-sdk AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM dhi.io/aspnetcore:10 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Using the official .NET 10 image" >}}
|
||||
|
||||
```Dockerfile {hl_lines="10-13"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
USER appuser
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
The following is the updated `compose.yaml` file.
|
||||
|
||||
```yaml {hl_lines=[5,15,16]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: development
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
db:
|
||||
image: postgres:18
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
```
|
||||
|
||||
Your containerized application will now use the SDK image (either `dhi.io/dotnet:10-sdk` for DHI or `mcr.microsoft.com/dotnet/sdk:10.0-alpine` for official images), which includes development tools like `dotnet test`. Continue to the next section to learn how you can run `dotnet test`.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you took a look at setting up your Compose file to add a local
|
||||
database and persist data. You also learned how to use Compose Watch to automatically rebuild and run your container when you update your code. And finally, you learned how to create a development container that contains the SDK tools and dependencies needed for development.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Compose file reference](/reference/compose-file/)
|
||||
- [Compose file watch](/manuals/compose/how-tos/file-watch.md)
|
||||
- [Multi-stage builds](/manuals/build/building/multi-stage.md)
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how to run unit tests using Docker.
|
||||
915
content/guides/dotnet/index.md
Normal file
915
content/guides/dotnet/index.md
Normal file
@@ -0,0 +1,915 @@
|
||||
---
|
||||
title: .NET language-specific guide
|
||||
linkTitle: C# (.NET)
|
||||
description: Containerize and develop .NET apps using Docker
|
||||
summary: |
|
||||
Learn how to containerize .NET applications using Docker.
|
||||
keywords: getting started, .net
|
||||
aliases:
|
||||
- /language/dotnet/
|
||||
- /guides/language/dotnet/
|
||||
- /language/dotnet/develop/
|
||||
- /language/dotnet/run-tests/
|
||||
- /language/dotnet/configure-ci-cd/
|
||||
- /language/dotnet/deploy/
|
||||
- /guides/dotnet/configure-ci-cd/
|
||||
- /guides/dotnet/containerize/
|
||||
- /guides/dotnet/deploy/
|
||||
- /guides/dotnet/develop/
|
||||
- /guides/dotnet/run-tests/
|
||||
params:
|
||||
tags: [languages]
|
||||
time: 20 minutes
|
||||
toc_min: 1
|
||||
toc_max: 2
|
||||
---
|
||||
|
||||
The .NET getting started guide teaches you how to create a containerized .NET application using Docker. In this guide, you'll learn how to:
|
||||
|
||||
- Containerize and run a .NET application
|
||||
- Set up a local environment to develop a .NET application using containers
|
||||
- Run tests for a .NET application using containers
|
||||
|
||||
After completing the .NET getting started modules, you should be able to containerize your own .NET application based on the examples and instructions provided in this guide.
|
||||
|
||||
Start by containerizing an existing .NET application.
|
||||
|
||||
## Containerize a .NET application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- You have installed the latest version of [Docker
|
||||
Desktop](/get-started/get-docker.md).
|
||||
- You have a [git client](https://git-scm.com/downloads). The examples in this
|
||||
section use a command-line based git client, but you can use any client.
|
||||
|
||||
### Overview
|
||||
|
||||
This section walks you through containerizing and running a .NET
|
||||
application.
|
||||
|
||||
### Get the sample applications
|
||||
|
||||
In this guide, you will use a pre-built .NET application. The application is
|
||||
similar to the application built in the Docker Blog article, [Building a
|
||||
Multi-Container .NET App Using Docker
|
||||
Desktop](https://www.docker.com/blog/building-multi-container-net-app-using-docker-desktop/).
|
||||
|
||||
Open a terminal, change directory to a directory that you want to work in, and
|
||||
run the following command to clone the repository.
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/docker/docker-dotnet-sample
|
||||
```
|
||||
|
||||
### Create Docker assets
|
||||
|
||||
Now that you have an application, you can create the necessary Docker assets to containerize it. You can choose between using the official .NET images or Docker Hardened Images (DHI).
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> [Gordon](/ai/gordon/), Docker's AI assistant, can generate Docker assets for your project. Ask Gordon to create a Dockerfile, Compose file, and `.dockerignore` tailored to your application.
|
||||
|
||||
> [Docker Hardened Images (DHIs)](https://docs.docker.com/dhi/) are minimal, secure, and production-ready container base and application images maintained by Docker. DHI images are recommended for better security—they are designed to reduce vulnerabilities and simplify compliance.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Using Docker Hardened Images" >}}
|
||||
|
||||
Docker Hardened Images (DHIs) for .NET are available in the [Docker Hardened Images catalog](https://hub.docker.com/hardened-images/catalog/dhi/aspnetcore). Docker Hardened Images are freely available to everyone with no subscription required. You can pull and use them like any other Docker image after signing in to the DHI registry. For more information, see the [DHI quickstart](/dhi/get-started/) guide.
|
||||
|
||||
1. Sign in to the DHI registry:
|
||||
|
||||
```console
|
||||
$ docker login dhi.io
|
||||
```
|
||||
|
||||
2. Pull the .NET SDK DHI (check the catalog for available versions):
|
||||
|
||||
```console
|
||||
$ docker pull dhi.io/dotnet:10-sdk
|
||||
```
|
||||
|
||||
3. Pull the ASP.NET Core runtime DHI (check the catalog for available versions):
|
||||
```console
|
||||
$ docker pull dhi.io/aspnetcore:10
|
||||
```
|
||||
|
||||
Create the following files in your `docker-dotnet-sample` directory.
|
||||
|
||||
```dockerfile {collapse=true,title=Dockerfile}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM dhi.io/aspnetcore:10 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> DHI runtime images already run as a non-root user (`nonroot`, UID 65532), so there's no need to create a user or specify `USER` in your Dockerfile. This reduces the attack surface and simplifies your configuration.
|
||||
|
||||
```yaml {collapse=true,title=compose.yaml}
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Docker Compose reference guide at
|
||||
# https://docs.docker.com/go/compose-spec-reference/
|
||||
|
||||
# Here the instructions define your application as a service called "server".
|
||||
# This service is built from the Dockerfile in the current directory.
|
||||
# You can add other services your application may depend on here, such as a
|
||||
# database or a cache. For examples, see the Awesome Compose repository:
|
||||
# https://github.com/docker/awesome-compose
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
||||
# The commented out section below is an example of how to define a PostgreSQL
|
||||
# database that your application can use. `depends_on` tells Docker Compose to
|
||||
# start the database before your application. The `db-data` volume persists the
|
||||
# database data between container restarts. The `db-password` secret is used
|
||||
# to set the database password. You must create `db/password.txt` and add
|
||||
# a password of your choosing to it before running `docker compose up`.
|
||||
# depends_on:
|
||||
# db:
|
||||
# condition: service_healthy
|
||||
# db:
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# user: postgres
|
||||
# secrets:
|
||||
# - db-password
|
||||
# volumes:
|
||||
# - db-data:/var/lib/postgresql/data
|
||||
# environment:
|
||||
# - POSTGRES_DB=example
|
||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
# expose:
|
||||
# - 5432
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "pg_isready" ]
|
||||
# interval: 10s
|
||||
# timeout: 5s
|
||||
# retries: 5
|
||||
# volumes:
|
||||
# db-data:
|
||||
# secrets:
|
||||
# db-password:
|
||||
# file: db/password.txt
|
||||
```
|
||||
|
||||
```text {collapse=true,title=".dockerignore"}
|
||||
# Include any files or directories that you don't want to be copied to your
|
||||
# container here (e.g., local build artifacts, temporary files, etc.).
|
||||
#
|
||||
# For more help, visit the .dockerignore file reference guide at
|
||||
# https://docs.docker.com/go/build-context-dockerignore/
|
||||
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/compose.y*ml
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Using the official .NET 10 image" >}}
|
||||
|
||||
Create the following files in your `docker-dotnet-sample` directory.
|
||||
|
||||
```dockerfile {collapse=true,title=Dockerfile}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
USER appuser
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
```yaml {collapse=true,title=compose.yaml}
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Docker Compose reference guide at
|
||||
# https://docs.docker.com/go/compose-spec-reference/
|
||||
|
||||
# Here the instructions define your application as a service called "server".
|
||||
# This service is built from the Dockerfile in the current directory.
|
||||
# You can add other services your application may depend on here, such as a
|
||||
# database or a cache. For examples, see the Awesome Compose repository:
|
||||
# https://github.com/docker/awesome-compose
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
||||
# The commented out section below is an example of how to define a PostgreSQL
|
||||
# database that your application can use. `depends_on` tells Docker Compose to
|
||||
# start the database before your application. The `db-data` volume persists the
|
||||
# database data between container restarts. The `db-password` secret is used
|
||||
# to set the database password. You must create `db/password.txt` and add
|
||||
# a password of your choosing to it before running `docker compose up`.
|
||||
# depends_on:
|
||||
# db:
|
||||
# condition: service_healthy
|
||||
# db:
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# user: postgres
|
||||
# secrets:
|
||||
# - db-password
|
||||
# volumes:
|
||||
# - db-data:/var/lib/postgresql/data
|
||||
# environment:
|
||||
# - POSTGRES_DB=example
|
||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
# expose:
|
||||
# - 5432
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "pg_isready" ]
|
||||
# interval: 10s
|
||||
# timeout: 5s
|
||||
# retries: 5
|
||||
# volumes:
|
||||
# db-data:
|
||||
# secrets:
|
||||
# db-password:
|
||||
# file: db/password.txt
|
||||
```
|
||||
|
||||
```text {collapse=true,title=".dockerignore"}
|
||||
# Include any files or directories that you don't want to be copied to your
|
||||
# container here (e.g., local build artifacts, temporary files, etc.).
|
||||
#
|
||||
# For more help, visit the .dockerignore file reference guide at
|
||||
# https://docs.docker.com/go/build-context-dockerignore/
|
||||
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/compose.y*ml
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
You should now have the following contents in your `docker-dotnet-sample`
|
||||
directory.
|
||||
|
||||
```text
|
||||
├── docker-dotnet-sample/
|
||||
│ ├── .git/
|
||||
│ ├── src/
|
||||
│ ├── .dockerignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── Dockerfile
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
To learn more about the files, see the following:
|
||||
|
||||
- [Dockerfile](/reference/dockerfile.md)
|
||||
- [.dockerignore](/reference/dockerfile.md#dockerignore-file)
|
||||
- [compose.yaml](/reference/compose-file/_index.md)
|
||||
|
||||
### Run the application
|
||||
|
||||
Inside the `docker-dotnet-sample` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application.
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
#### Run the application in the background
|
||||
|
||||
You can run the application detached from the terminal by adding the `-d`
|
||||
option. Inside the `docker-dotnet-sample` directory, run the following command
|
||||
in a terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build -d
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application.
|
||||
|
||||
In the terminal, run the following command to stop the application.
|
||||
|
||||
```console
|
||||
$ docker compose down
|
||||
```
|
||||
|
||||
For more information about Compose commands, see the [Compose CLI
|
||||
reference](/reference/cli/docker/compose/).
|
||||
|
||||
## Use containers for .NET development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Complete [Containerize a .NET application](./).
|
||||
|
||||
### Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment for your containerized application. This includes:
|
||||
|
||||
- Adding a local database and persisting data
|
||||
- Configuring Compose to automatically update your running Compose services as you edit and save your code
|
||||
- Creating a development container that contains the .NET Core SDK tools and dependencies
|
||||
|
||||
### Update the application
|
||||
|
||||
This section uses a different branch of the `docker-dotnet-sample` repository
|
||||
that contains an updated .NET application. The updated application is on the
|
||||
`add-db` branch of the repository you cloned in [Containerize a .NET
|
||||
application](./).
|
||||
|
||||
To get the updated code, you need to checkout the `add-db` branch. For the changes you made in [Containerize a .NET application](./), for this section, you can stash them. In a terminal, run the following commands in the `docker-dotnet-sample` directory.
|
||||
|
||||
1. Stash any previous changes.
|
||||
|
||||
```console
|
||||
$ git stash -u
|
||||
```
|
||||
|
||||
2. Check out the new branch with the updated application.
|
||||
|
||||
```console
|
||||
$ git checkout add-db
|
||||
```
|
||||
|
||||
In the `add-db` branch, only the .NET application has been updated. None of the Docker assets have been updated yet.
|
||||
|
||||
You should now have the following in your `docker-dotnet-sample` directory.
|
||||
|
||||
```text
|
||||
├── docker-dotnet-sample/
|
||||
│ ├── .git/
|
||||
│ ├── src/
|
||||
│ │ ├── Data/
|
||||
│ │ ├── Models/
|
||||
│ │ ├── Pages/
|
||||
│ │ ├── Properties/
|
||||
│ │ ├── wwwroot/
|
||||
│ │ ├── appsettings.Development.json
|
||||
│ │ ├── appsettings.json
|
||||
│ │ ├── myWebApp.csproj
|
||||
│ │ └── Program.cs
|
||||
│ ├── tests/
|
||||
│ │ ├── tests.csproj
|
||||
│ │ ├── UnitTest1.cs
|
||||
│ │ └── Usings.cs
|
||||
│ ├── .dockerignore
|
||||
│ ├── .gitignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── Dockerfile
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
### Add a local database and persist data
|
||||
|
||||
You can use containers to set up local services, like a database. In this section, you'll update the `compose.yaml` file to define a database service and a volume to persist data.
|
||||
|
||||
Open the `compose.yaml` file in an IDE or text editor. You'll notice it
|
||||
already contains commented-out instructions for a PostgreSQL database and volume.
|
||||
|
||||
Open `docker-dotnet-sample/src/appsettings.json` in an IDE or text editor. You'll
|
||||
notice the connection string with all the database information. The
|
||||
`compose.yaml` already contains this information, but it's commented out.
|
||||
Uncomment the database instructions in the `compose.yaml` file.
|
||||
|
||||
The following is the updated `compose.yaml` file.
|
||||
|
||||
```yaml {hl_lines="8-33"}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
db:
|
||||
image: postgres:18
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> To learn more about the instructions in the Compose file, see [Compose file
|
||||
> reference](/reference/compose-file/).
|
||||
|
||||
Before you run the application using Compose, notice that this Compose file uses
|
||||
`secrets` and specifies a `password.txt` file to hold the database's password.
|
||||
You must create this file as it's not included in the source repository.
|
||||
|
||||
In the `docker-dotnet-sample` directory, create a new directory named `db` and
|
||||
inside that directory create a file named `password.txt`. Open `password.txt` in an IDE or text editor and add the following password. The password must be on a single line, with no additional lines in the file.
|
||||
|
||||
```text
|
||||
example
|
||||
```
|
||||
|
||||
Save and close the `password.txt` file.
|
||||
|
||||
You should now have the following in your `docker-dotnet-sample` directory.
|
||||
|
||||
```text
|
||||
├── docker-dotnet-sample/
|
||||
│ ├── .git/
|
||||
│ ├── db/
|
||||
│ │ └── password.txt
|
||||
│ ├── src/
|
||||
│ ├── tests/
|
||||
│ ├── .dockerignore
|
||||
│ ├── .gitignore
|
||||
│ ├── compose.yaml
|
||||
│ ├── Dockerfile
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
Run the following command to start your application.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application with the text `Student name is`.
|
||||
|
||||
The application doesn't display a name because the database is empty. For this application, you need to access the database and then add records.
|
||||
|
||||
### Add records to the database
|
||||
|
||||
For the sample application, you must access the database directly to create sample records.
|
||||
|
||||
You can run commands inside the database container using the `docker exec`
|
||||
command. Before running that command, you must get the ID of the database
|
||||
container. Open a new terminal window and run the following command to list all
|
||||
your running containers.
|
||||
|
||||
```console
|
||||
$ docker container ls
|
||||
```
|
||||
|
||||
You should see output like the following.
|
||||
|
||||
```console
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
cb36e310aa7e docker-dotnet-sample-server "dotnet myWebApp.dll" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp docker-dotnet-sample-server-1
|
||||
39fdcf0aff7b postgres:18 "docker-entrypoint.s…" About a minute ago Up About a minute (healthy) 5432/tcp docker-dotnet-sample-db-1
|
||||
```
|
||||
|
||||
In the previous example, the container ID is `39fdcf0aff7b`. Run the following command to connect to the postgres database in the container. Replace the container ID with your own container ID.
|
||||
|
||||
```console
|
||||
$ docker exec -it 39fdcf0aff7b psql -d example -U postgres
|
||||
```
|
||||
|
||||
And finally, insert a record into the database.
|
||||
|
||||
```console
|
||||
example=# INSERT INTO "Students" ("ID", "LastName", "FirstMidName", "EnrollmentDate") VALUES (DEFAULT, 'Whale', 'Moby', '2013-03-20');
|
||||
```
|
||||
|
||||
You should see output like the following.
|
||||
|
||||
```console
|
||||
INSERT 0 1
|
||||
```
|
||||
|
||||
Close the database connection and exit the container shell by running `exit`.
|
||||
|
||||
```console
|
||||
example=# exit
|
||||
```
|
||||
|
||||
### Verify that data persists in the database
|
||||
|
||||
Open a browser and view the application at [http://localhost:8080](http://localhost:8080). You should see a simple web application with the text `Student name is Moby Whale`.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
In the terminal, run `docker compose rm` to remove your containers and then run `docker compose up` to run your application again.
|
||||
|
||||
```console
|
||||
$ docker compose rm
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Refresh [http://localhost:8080](http://localhost:8080) in your browser and verify that the student name persisted, even after the containers were removed and ran again.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
### Automatically update services
|
||||
|
||||
Use Compose Watch to automatically update your running Compose services as you edit and save your code. For more details about Compose Watch, see [Use Compose Watch](/manuals/compose/how-tos/file-watch.md).
|
||||
|
||||
Open your `compose.yaml` file in an IDE or text editor and then add the Compose Watch instructions. The following is the updated `compose.yaml` file.
|
||||
|
||||
```yaml {hl_lines="11-14"}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: final
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
db:
|
||||
image: postgres:18
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
```
|
||||
|
||||
Run the following command to run your application with Compose Watch.
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Open a browser and verify that the application is running at [http://localhost:8080](http://localhost:8080).
|
||||
|
||||
Any changes to the application's source files on your local machine will now be
|
||||
immediately reflected in the running container.
|
||||
|
||||
Open `docker-dotnet-sample/src/Pages/Index.cshtml` in an IDE or text editor and update the student name text on line 13 from `Student name is` to `Student name:`.
|
||||
|
||||
```diff
|
||||
- <p>Student name is @Model.StudentName</p>
|
||||
+ <p>Student name: @Model.StudentName</p>
|
||||
```
|
||||
|
||||
Save the changes to `Index.cshtml` and then wait a few seconds for the application to rebuild. Refresh [http://localhost:8080](http://localhost:8080) in your browser and verify that the updated text appears.
|
||||
|
||||
Press `ctrl+c` in the terminal to stop your application.
|
||||
|
||||
### Create a development container
|
||||
|
||||
At this point, when you run your containerized application, it's using the .NET runtime image. While this small image is good for production, it lacks the SDK tools and dependencies you may need when developing. Also, during development, you may not need to run `dotnet publish`. You can use multi-stage builds to build stages for both development and production in the same Dockerfile. For more details, see [Multi-stage builds](/manuals/build/building/multi-stage.md).
|
||||
|
||||
Add a new development stage to your Dockerfile and update your `compose.yaml` file to use this stage for local development.
|
||||
|
||||
The following is the updated Dockerfile.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Using Docker Hardened Images" >}}
|
||||
|
||||
```Dockerfile {hl_lines="10-13"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM dhi.io/dotnet:10-sdk AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM dhi.io/aspnetcore:10 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Using the official .NET 10 image" >}}
|
||||
|
||||
```Dockerfile {hl_lines="10-13"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
USER appuser
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
The following is the updated `compose.yaml` file.
|
||||
|
||||
```yaml {hl_lines=[5,15,16]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
target: development
|
||||
ports:
|
||||
- 8080:8080
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
develop:
|
||||
watch:
|
||||
- action: rebuild
|
||||
path: .
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
db:
|
||||
image: postgres:18
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
volumes:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
```
|
||||
|
||||
Your containerized application will now use the SDK image (either `dhi.io/dotnet:10-sdk` for DHI or `mcr.microsoft.com/dotnet/sdk:10.0-alpine` for official images), which includes development tools like `dotnet test`. Continue to the next section to learn how you can run `dotnet test`.
|
||||
|
||||
## Run .NET tests in a container
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Complete all the previous sections of this guide, starting with [Containerize a .NET application](./).
|
||||
|
||||
### Overview
|
||||
|
||||
Testing is an essential part of modern software development. Testing can mean a
|
||||
lot of things to different development teams. There are unit tests, integration
|
||||
tests and end-to-end testing. In this guide you take a look at running your unit
|
||||
tests in Docker when developing and when building.
|
||||
|
||||
### Run tests when developing locally
|
||||
|
||||
The sample application already has an xUnit test inside the `tests` directory. When developing locally, you can use Compose to run your tests.
|
||||
|
||||
Run the following command in the `docker-dotnet-sample` directory to run the tests inside a container.
|
||||
|
||||
```console
|
||||
$ docker compose run --build --rm server dotnet test /source/tests
|
||||
```
|
||||
|
||||
You should see output that contains the following.
|
||||
|
||||
```console
|
||||
Starting test execution, please wait...
|
||||
A total of 1 test files matched the specified pattern.
|
||||
|
||||
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: < 1 ms - /source/tests/bin/Debug/net10.0/tests.dll (net10.0)
|
||||
```
|
||||
|
||||
To learn more about the command, see [docker compose run](/reference/cli/docker/compose/run/).
|
||||
|
||||
### Run tests when building
|
||||
|
||||
To run your tests when building, you need to update your Dockerfile. You can create a new test stage that runs the tests, or run the tests in the existing build stage. For this guide, update the Dockerfile to run the tests in the build stage.
|
||||
|
||||
The following is the updated Dockerfile.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Using Docker Hardened Images" >}}
|
||||
|
||||
```dockerfile {hl_lines="9"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
RUN dotnet test /source/tests
|
||||
|
||||
FROM dhi.io/dotnet:10-sdk AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM dhi.io/aspnetcore:10 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Using the official .NET 10 image" >}}
|
||||
|
||||
```dockerfile {hl_lines="9"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
RUN dotnet test /source/tests
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
USER appuser
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
Run the following command to build an image using the build stage as the target and view the test results. Include `--progress=plain` to view the build output, `--no-cache` to ensure the tests always run, and `--target build` to target the build stage.
|
||||
|
||||
```console
|
||||
$ docker build -t dotnet-docker-image-test --progress=plain --no-cache --target build .
|
||||
```
|
||||
|
||||
You should see output containing the following.
|
||||
|
||||
```console
|
||||
#11 [build 5/5] RUN dotnet test /source/tests
|
||||
#11 1.564 Determining projects to restore...
|
||||
#11 3.421 Restored /source/src/myWebApp.csproj (in 1.02 sec).
|
||||
#11 19.42 Restored /source/tests/tests.csproj (in 17.05 sec).
|
||||
#11 27.91 myWebApp -> /source/src/bin/Debug/net10.0/myWebApp.dll
|
||||
#11 28.47 tests -> /source/tests/bin/Debug/net10.0/tests.dll
|
||||
#11 28.49 Test run for /source/tests/bin/Debug/net10.0/tests.dll (.NETCoreApp,Version=v10.0)
|
||||
#11 28.67 Microsoft (R) Test Execution Command Line Tool Version 17.3.3 (x64)
|
||||
#11 28.67 Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
#11 28.68
|
||||
#11 28.97 Starting test execution, please wait...
|
||||
#11 29.03 A total of 1 test files matched the specified pattern.
|
||||
#11 32.07
|
||||
#11 32.08 Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: < 1 ms - /source/tests/bin/Debug/net10.0/tests.dll (net10.0)
|
||||
#11 DONE 32.2s
|
||||
```
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you learned how to run tests when developing locally using Compose and how to run tests when building your image.
|
||||
|
||||
Related information:
|
||||
|
||||
- [docker compose run](/reference/cli/docker/compose/run/)
|
||||
@@ -1,146 +0,0 @@
|
||||
---
|
||||
title: Run .NET tests in a container
|
||||
linkTitle: Run your tests
|
||||
weight: 30
|
||||
keywords: .NET, test
|
||||
description: Learn how to run your .NET tests in a container.
|
||||
aliases:
|
||||
- /language/dotnet/run-tests/
|
||||
- /guides/language/dotnet/run-tests/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete all the previous sections of this guide, starting with [Containerize a .NET application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
Testing is an essential part of modern software development. Testing can mean a
|
||||
lot of things to different development teams. There are unit tests, integration
|
||||
tests and end-to-end testing. In this guide you take a look at running your unit
|
||||
tests in Docker when developing and when building.
|
||||
|
||||
## Run tests when developing locally
|
||||
|
||||
The sample application already has an xUnit test inside the `tests` directory. When developing locally, you can use Compose to run your tests.
|
||||
|
||||
Run the following command in the `docker-dotnet-sample` directory to run the tests inside a container.
|
||||
|
||||
```console
|
||||
$ docker compose run --build --rm server dotnet test /source/tests
|
||||
```
|
||||
|
||||
You should see output that contains the following.
|
||||
|
||||
```console
|
||||
Starting test execution, please wait...
|
||||
A total of 1 test files matched the specified pattern.
|
||||
|
||||
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: < 1 ms - /source/tests/bin/Debug/net10.0/tests.dll (net10.0)
|
||||
```
|
||||
|
||||
To learn more about the command, see [docker compose run](/reference/cli/docker/compose/run/).
|
||||
|
||||
## Run tests when building
|
||||
|
||||
To run your tests when building, you need to update your Dockerfile. You can create a new test stage that runs the tests, or run the tests in the existing build stage. For this guide, update the Dockerfile to run the tests in the build stage.
|
||||
|
||||
The following is the updated Dockerfile.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Using Docker Hardened Images" >}}
|
||||
|
||||
```dockerfile {hl_lines="9"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM dhi.io/dotnet:10-sdk AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
RUN dotnet test /source/tests
|
||||
|
||||
FROM dhi.io/dotnet:10-sdk AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM dhi.io/aspnetcore:10 AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Using the official .NET 10 image" >}}
|
||||
|
||||
```dockerfile {hl_lines="9"}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
|
||||
ARG TARGETARCH
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
RUN --mount=type=cache,id=nuget,target=/root/.nuget/packages \
|
||||
dotnet publish -a ${TARGETARCH/amd64/x64} --use-current-runtime --self-contained false -o /app
|
||||
RUN dotnet test /source/tests
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS development
|
||||
COPY . /source
|
||||
WORKDIR /source/src
|
||||
CMD dotnet run --no-launch-profile
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
|
||||
WORKDIR /app
|
||||
COPY --from=build /app .
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
USER appuser
|
||||
ENTRYPOINT ["dotnet", "myWebApp.dll"]
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
Run the following command to build an image using the build stage as the target and view the test results. Include `--progress=plain` to view the build output, `--no-cache` to ensure the tests always run, and `--target build` to target the build stage.
|
||||
|
||||
```console
|
||||
$ docker build -t dotnet-docker-image-test --progress=plain --no-cache --target build .
|
||||
```
|
||||
|
||||
You should see output containing the following.
|
||||
|
||||
```console
|
||||
#11 [build 5/5] RUN dotnet test /source/tests
|
||||
#11 1.564 Determining projects to restore...
|
||||
#11 3.421 Restored /source/src/myWebApp.csproj (in 1.02 sec).
|
||||
#11 19.42 Restored /source/tests/tests.csproj (in 17.05 sec).
|
||||
#11 27.91 myWebApp -> /source/src/bin/Debug/net10.0/myWebApp.dll
|
||||
#11 28.47 tests -> /source/tests/bin/Debug/net10.0/tests.dll
|
||||
#11 28.49 Test run for /source/tests/bin/Debug/net10.0/tests.dll (.NETCoreApp,Version=v10.0)
|
||||
#11 28.67 Microsoft (R) Test Execution Command Line Tool Version 17.3.3 (x64)
|
||||
#11 28.67 Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
#11 28.68
|
||||
#11 28.97 Starting test execution, please wait...
|
||||
#11 29.03 A total of 1 test files matched the specified pattern.
|
||||
#11 32.07
|
||||
#11 32.08 Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: < 1 ms - /source/tests/bin/Debug/net10.0/tests.dll (net10.0)
|
||||
#11 DONE 32.2s
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to run tests when developing locally using Compose and how to run tests when building your image.
|
||||
|
||||
Related information:
|
||||
|
||||
- [docker compose run](/reference/cli/docker/compose/run/)
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
---
|
||||
title: Develop and Deploy Laravel applications with Docker Compose
|
||||
linkTitle: Laravel
|
||||
summary: Learn how to efficiently set up Laravel development and production environments using Docker Compose.
|
||||
description: A guide on using Docker Compose to manage Laravel applications for development and production, covering container configurations and service management.
|
||||
keywords: laravel, php, docker compose, web framework, development, production
|
||||
tags: [frameworks]
|
||||
languages: [php]
|
||||
aliases:
|
||||
- /frameworks/laravel/
|
||||
params:
|
||||
time: 30 minutes
|
||||
resource_links:
|
||||
- title: Laravel
|
||||
url: https://laravel.com/
|
||||
- title: Docker Compose
|
||||
url: /compose/
|
||||
- title: Use Compose in production
|
||||
url: /compose/how-tos/production/
|
||||
- title: Repository with examples
|
||||
url: https://github.com/dockersamples/laravel-docker-examples
|
||||
---
|
||||
|
||||
Laravel is a popular PHP framework that allows developers to build web applications quickly and effectively. Docker Compose simplifies the management of development and production environments by defining essential services, like PHP, a web server, and a database, in a single YAML file. This guide provides a streamlined approach to setting up a robust Laravel environment using Docker Compose, focusing on simplicity and efficiency.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Sergei Shitikov](https://github.com/rw4lll) for
|
||||
> his contribution to this guide.
|
||||
|
||||
The demonstrated examples can be found in [this GitHub repository](https://github.com/dockersamples/laravel-docker-examples). Docker Compose offers a straightforward approach to connecting multiple containers for Laravel, though similar setups can also be achieved using tools like Docker Swarm, Kubernetes, or individual Docker containers.
|
||||
|
||||
This guide is intended for educational purposes, helping developers adapt and optimize configurations for their specific use cases. Additionally, there are existing tools that support Laravel in containers:
|
||||
|
||||
- [Laravel Sail](https://laravel.com/docs/12.x/sail): An official package for easily starting Laravel in Docker.
|
||||
- [Laradock](https://github.com/laradock/laradock): A community project that helps run Laravel applications in Docker.
|
||||
|
||||
## What you’ll learn
|
||||
|
||||
- How to use Docker Compose to set up a Laravel development and production environment.
|
||||
- Defining services that make Laravel development easier, including PHP-FPM, Nginx, and database containers.
|
||||
- Best practices for managing Laravel environments using containerization.
|
||||
|
||||
## Who’s this for?
|
||||
|
||||
- Developers who work with Laravel and want to streamline environment management.
|
||||
- DevOps engineers seeking efficient ways to manage and deploy Laravel applications.
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
title: Common Questions on Using Laravel with Docker
|
||||
description: Find answers to common questions about setting up and managing Laravel environments with Docker Compose, including troubleshooting and best practices.
|
||||
keywords: laravel, php, docker compose, faq, troubleshooting, best practices
|
||||
weight: 40
|
||||
---
|
||||
|
||||
<!-- vale Docker.HeadingLength = NO -->
|
||||
|
||||
## 1. Why should I use Docker Compose for Laravel?
|
||||
|
||||
Docker Compose is a powerful tool for managing multi-container environments, particularly in development due to its simplicity. With Docker Compose, you can define and connect all necessary services for Laravel, such as PHP, Nginx, and databases, in a single configuration (`compose.*.yaml`). This setup ensures consistency across development, testing, and production environments, streamlining onboarding and reducing discrepancies between local and server setups.
|
||||
|
||||
While Docker Compose is a great choice for development, tools like **Docker Swarm** or **Kubernetes** offer advanced scaling and orchestration features, which may be beneficial for complex production deployments.
|
||||
|
||||
## 2. How do I debug my Laravel application with Docker Compose?
|
||||
|
||||
To debug your Laravel application in a Docker environment, use **Xdebug**. In the development setup, Xdebug is installed in the `php-fpm` container to enable debugging. Ensure Xdebug is enabled in your `compose.dev.yaml` file by setting the environment variable `XDEBUG_ENABLED=true` and configuring your IDE (e.g., Visual Studio Code or PHPStorm) to connect to the remote container for debugging.
|
||||
|
||||
## 3. Can I use Docker Compose with databases other than PostgreSQL?
|
||||
|
||||
Yes, Docker Compose supports various database services for Laravel. While PostgreSQL is used in the examples, you can easily substitute **MySQL**, **MariaDB**, or even **SQLite**. Update the `compose.*.yaml` file to specify the required Docker image and adjust your `.env` file to reflect the new database configuration.
|
||||
|
||||
## 4. How can I persist data in development and production?
|
||||
|
||||
In both development and production, Docker volumes are used to persist data. For instance, in the `compose.*.yaml` file, the `postgres-data-*` volume stores PostgreSQL data, ensuring that data is retained even if the container restarts. You can also define named volumes for other services where data persistence is essential.
|
||||
|
||||
## 5. What is the difference between development and production Docker configurations?
|
||||
|
||||
In a development environment, Docker configurations include tools that streamline coding and debugging, such as Xdebug for debugging, and volume mounts to enable real-time code updates without requiring image rebuilds.
|
||||
|
||||
In production, the configuration is optimized for performance, security, and efficiency. This setup uses multi-stage builds to keep the image lightweight and includes only essential tools, packages, and libraries.
|
||||
|
||||
It’s recommended to use `alpine`-based images in production for smaller image sizes, enhancing deployment speed and security.
|
||||
|
||||
Additionally, consider using [Docker Scout](/manuals/scout/_index.md) to detect and analyze vulnerabilities, especially in production environments.
|
||||
|
||||
For additional information about using Docker Compose in production, see [this guide](/compose/how-tos/production/).
|
||||
@@ -1,328 +0,0 @@
|
||||
---
|
||||
title: Laravel Development Setup with Docker Compose
|
||||
description: Set up a Laravel development environment using Docker Compose.
|
||||
keywords: laravel, php, docker compose, development, xdebug, php-fpm, nginx
|
||||
weight: 30
|
||||
---
|
||||
|
||||
This guide demonstrates how to configure a **development** environment for a Laravel application using Docker and Docker Compose. It builds **on top of** the production image for PHP-FPM and then adds developer-focused features—like Xdebug—to streamline debugging. By basing the development container on a known production image, you keep both environments closely aligned.
|
||||
|
||||
This setup includes PHP-FPM, Nginx, and PostgreSQL services (although you can easily swap PostgreSQL for another database, like MySQL or MariaDB). Everything runs in containers, so you can develop in isolation without altering your host system.
|
||||
|
||||
> [!NOTE]
|
||||
> To experiment with a ready-to-run configuration, download the [Laravel Docker Examples](https://github.com/dockersamples/laravel-docker-examples) repository. It contains pre-configured setups for both development and production.
|
||||
|
||||
## Project structure
|
||||
|
||||
```plaintext
|
||||
my-laravel-app/
|
||||
├── app/
|
||||
├── bootstrap/
|
||||
├── config/
|
||||
├── database/
|
||||
├── public/
|
||||
├── docker/
|
||||
│ ├── common/
|
||||
│ │ └── php-fpm/
|
||||
│ │ └── Dockerfile
|
||||
│ ├── development/
|
||||
│ │ ├── php-fpm/
|
||||
│ │ │ └── entrypoint.sh
|
||||
│ │ ├── workspace/
|
||||
│ │ │ └── Dockerfile
|
||||
│ │ └── nginx
|
||||
│ │ ├── Dockerfile
|
||||
│ │ └── nginx.conf
|
||||
│ └── production/
|
||||
├── compose.dev.yaml
|
||||
├── compose.prod.yaml
|
||||
├── .dockerignore
|
||||
├── .env
|
||||
├── vendor/
|
||||
├── ...
|
||||
```
|
||||
|
||||
This layout represents a typical Laravel project, with Docker configurations stored in a unified `docker` directory. You’ll find **two** Compose files — `compose.dev.yaml` (for development) and `compose.prod.yaml` (for production) — to keep your environments separate and manageable.
|
||||
|
||||
The environment includes a `workspace` service, a sidecar container for tasks like building front-end assets, running Artisan commands, and other CLI tools your project may require. While this extra container may seem unusual, it’s a familiar pattern in solutions like **Laravel Sail** and **Laradock**. It also includes **Xdebug** to aid in debugging.
|
||||
|
||||
## Create a Dockerfile for PHP-FPM
|
||||
|
||||
This Dockerfile **extends** the production image by installing Xdebug and adjusting user permissions to ease local development. That way, your development environment stays consistent with production while still offering extra debug features and improved file mounting.
|
||||
|
||||
```dockerfile
|
||||
# Builds a dev-only layer on top of the production image
|
||||
FROM production AS development
|
||||
|
||||
# Use ARGs to define environment variables passed from the Docker build command or Docker Compose.
|
||||
ARG XDEBUG_ENABLED=true
|
||||
ARG XDEBUG_MODE=develop,coverage,debug,profile
|
||||
ARG XDEBUG_HOST=host.docker.internal
|
||||
ARG XDEBUG_IDE_KEY=DOCKER
|
||||
ARG XDEBUG_LOG=/dev/stdout
|
||||
ARG XDEBUG_LOG_LEVEL=0
|
||||
|
||||
USER root
|
||||
|
||||
# Configure Xdebug if enabled
|
||||
RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \
|
||||
pecl install xdebug && \
|
||||
docker-php-ext-enable xdebug && \
|
||||
echo "xdebug.mode=${XDEBUG_MODE}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.idekey=${XDEBUG_IDE_KEY}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log=${XDEBUG_LOG}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.client_host=${XDEBUG_HOST}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
fi
|
||||
|
||||
# Add ARGs for syncing permissions
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
|
||||
# Create a new user with the specified UID and GID, reusing an existing group if GID exists
|
||||
RUN if getent group ${GID}; then \
|
||||
group_name=$(getent group ${GID} | cut -d: -f1); \
|
||||
useradd -m -u ${UID} -g ${GID} -s /bin/bash www; \
|
||||
else \
|
||||
groupadd -g ${GID} www && \
|
||||
useradd -m -u ${UID} -g www -s /bin/bash www; \
|
||||
group_name=www; \
|
||||
fi
|
||||
|
||||
# Dynamically update php-fpm to use the new user and group
|
||||
RUN sed -i "s/user = www-data/user = www/g" /usr/local/etc/php-fpm.d/www.conf && \
|
||||
sed -i "s/group = www-data/group = $group_name/g" /usr/local/etc/php-fpm.d/www.conf
|
||||
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy the entrypoint script
|
||||
COPY ./docker/development/php-fpm/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
# Switch back to the non-privileged user to run the application
|
||||
USER www-data
|
||||
|
||||
# Change the default command to run the entrypoint script
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
# Expose port 9000 and start php-fpm server
|
||||
EXPOSE 9000
|
||||
CMD ["php-fpm"]
|
||||
```
|
||||
|
||||
## Create a Dockerfile for Workspace
|
||||
|
||||
A workspace container provides a dedicated shell for asset compilation, Artisan/Composer commands, and other CLI tasks. This approach follows patterns from Laravel Sail and Laradock, consolidating all development tools into one container for convenience.
|
||||
|
||||
```dockerfile
|
||||
# docker/development/workspace/Dockerfile
|
||||
# Use the official PHP CLI image as the base
|
||||
FROM php:8.5-cli
|
||||
|
||||
# Set environment variables for user and group ID
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
ARG NODE_VERSION=22.0.0
|
||||
|
||||
# Install system dependencies and build libraries
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
unzip \
|
||||
libpq-dev \
|
||||
libonig-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
pdo_mysql \
|
||||
pdo_pgsql \
|
||||
pgsql \
|
||||
intl \
|
||||
zip \
|
||||
bcmath \
|
||||
soap \
|
||||
&& pecl install redis \
|
||||
&& docker-php-ext-enable redis \
|
||||
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Use ARG to define environment variables passed from the Docker build command or Docker Compose.
|
||||
ARG XDEBUG_ENABLED
|
||||
ARG XDEBUG_MODE
|
||||
ARG XDEBUG_HOST
|
||||
ARG XDEBUG_IDE_KEY
|
||||
ARG XDEBUG_LOG
|
||||
ARG XDEBUG_LOG_LEVEL
|
||||
|
||||
# Configure Xdebug if enabled
|
||||
RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \
|
||||
pecl install xdebug && \
|
||||
docker-php-ext-enable xdebug && \
|
||||
echo "xdebug.mode=${XDEBUG_MODE}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.idekey=${XDEBUG_IDE_KEY}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log=${XDEBUG_LOG}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.client_host=${XDEBUG_HOST}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
fi
|
||||
|
||||
# If the group already exists, use it; otherwise, create the 'www' group
|
||||
RUN if getent group ${GID}; then \
|
||||
useradd -m -u ${UID} -g ${GID} -s /bin/bash www; \
|
||||
else \
|
||||
groupadd -g ${GID} www && \
|
||||
useradd -m -u ${UID} -g www -s /bin/bash www; \
|
||||
fi && \
|
||||
usermod -aG sudo www && \
|
||||
echo 'www ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||
|
||||
# Switch to the non-root user to install NVM and Node.js
|
||||
USER www
|
||||
|
||||
# Install NVM (Node Version Manager) as the www user
|
||||
RUN export NVM_DIR="$HOME/.nvm" && \
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash && \
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && \
|
||||
nvm install ${NODE_VERSION} && \
|
||||
nvm alias default ${NODE_VERSION} && \
|
||||
nvm use default
|
||||
|
||||
# Ensure NVM is available for all future shells
|
||||
RUN echo 'export NVM_DIR="$HOME/.nvm"' >> /home/www/.bashrc && \
|
||||
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> /home/www/.bashrc && \
|
||||
echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> /home/www/.bashrc
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Override the entrypoint to avoid the default php entrypoint
|
||||
ENTRYPOINT []
|
||||
|
||||
# Default command to keep the container running
|
||||
CMD ["bash"]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you prefer a **one-service-per-container** approach, simply omit the workspace container and run separate containers for each task. For example, you could use a dedicated `php-cli` container for your PHP scripts, and a `node` container to handle the asset building.
|
||||
|
||||
## Create a Docker Compose configuration for development
|
||||
|
||||
Here's the `compose.yaml` file to set up the development environment:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
image: nginx:latest # Using the default Nginx image with custom configuration.
|
||||
volumes:
|
||||
# Mount the application code for live updates
|
||||
- ./:/var/www
|
||||
# Mount the Nginx configuration file
|
||||
- ./docker/development/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
ports:
|
||||
# Map port 80 inside the container to the port specified by 'NGINX_PORT' on the host machine
|
||||
- "80:80"
|
||||
environment:
|
||||
- NGINX_HOST=localhost
|
||||
networks:
|
||||
- laravel-development
|
||||
depends_on:
|
||||
php-fpm:
|
||||
condition: service_started # Wait for php-fpm to start
|
||||
|
||||
php-fpm:
|
||||
# For the php-fpm service, we will use our common PHP-FPM Dockerfile with the development target
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/common/php-fpm/Dockerfile
|
||||
target: development
|
||||
args:
|
||||
UID: ${UID:-1000}
|
||||
GID: ${GID:-1000}
|
||||
XDEBUG_ENABLED: ${XDEBUG_ENABLED:-true}
|
||||
XDEBUG_MODE: develop,coverage,debug,profile
|
||||
XDEBUG_HOST: ${XDEBUG_HOST:-host.docker.internal}
|
||||
XDEBUG_IDE_KEY: ${XDEBUG_IDE_KEY:-DOCKER}
|
||||
XDEBUG_LOG: /dev/stdout
|
||||
XDEBUG_LOG_LEVEL: 0
|
||||
env_file:
|
||||
# Load the environment variables from the Laravel application
|
||||
- .env
|
||||
user: "${UID:-1000}:${GID:-1000}"
|
||||
volumes:
|
||||
# Mount the application code for live updates
|
||||
- ./:/var/www
|
||||
networks:
|
||||
- laravel-development
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_started # Wait for postgres to start
|
||||
|
||||
workspace:
|
||||
# For the workspace service, we will also create a custom image to install and setup all the necessary stuff.
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/development/workspace/Dockerfile
|
||||
args:
|
||||
UID: ${UID:-1000}
|
||||
GID: ${GID:-1000}
|
||||
XDEBUG_ENABLED: ${XDEBUG_ENABLED:-true}
|
||||
XDEBUG_MODE: develop,coverage,debug,profile
|
||||
XDEBUG_HOST: ${XDEBUG_HOST:-host.docker.internal}
|
||||
XDEBUG_IDE_KEY: ${XDEBUG_IDE_KEY:-DOCKER}
|
||||
XDEBUG_LOG: /dev/stdout
|
||||
XDEBUG_LOG_LEVEL: 0
|
||||
tty: true # Enables an interactive terminal
|
||||
stdin_open: true # Keeps standard input open for 'docker exec'
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- ./:/var/www
|
||||
networks:
|
||||
- laravel-development
|
||||
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
environment:
|
||||
- POSTGRES_DB=app
|
||||
- POSTGRES_USER=laravel
|
||||
- POSTGRES_PASSWORD=secret
|
||||
volumes:
|
||||
- postgres-data-development:/var/lib/postgresql
|
||||
networks:
|
||||
- laravel-development
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
networks:
|
||||
- laravel-development
|
||||
|
||||
networks:
|
||||
laravel-development:
|
||||
|
||||
volumes:
|
||||
postgres-data-development:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Ensure you have an `.env` file at the root of your Laravel project with the necessary configurations. You can use the `.env.example` file as a template.
|
||||
|
||||
## Run your development environment
|
||||
|
||||
To start the development environment, use:
|
||||
|
||||
```console
|
||||
$ docker compose -f compose.dev.yaml up --build -d
|
||||
```
|
||||
|
||||
Run this command to build and start the development environment in detached mode. When the containers finish initializing, visit [http://localhost/](http://localhost/) to see your Laravel app in action.
|
||||
|
||||
## Summary
|
||||
|
||||
By building on top of the production image and adding debug tools like Xdebug, you create a Laravel development workflow that closely mirrors production. The optional workspace container simplifies tasks like asset building and running Artisan commands. If you prefer a separate container for every service (e.g., a dedicated `php-cli` and `node` container), you can skip the workspace approach. Either way, Docker Compose provides an efficient, consistent way to develop your Laravel project.
|
||||
862
content/guides/frameworks/laravel/index.md
Normal file
862
content/guides/frameworks/laravel/index.md
Normal file
@@ -0,0 +1,862 @@
|
||||
---
|
||||
title: Develop and Deploy Laravel applications with Docker Compose
|
||||
linkTitle: Laravel
|
||||
summary: Learn how to efficiently set up Laravel development and production environments using Docker Compose.
|
||||
description: A guide on using Docker Compose to manage Laravel applications for development and production, covering container configurations and service management.
|
||||
keywords: laravel, php, docker compose, web framework, development, production
|
||||
aliases:
|
||||
- /frameworks/laravel/
|
||||
- /guides/frameworks/laravel/common-questions/
|
||||
- /guides/frameworks/laravel/development-setup/
|
||||
- /guides/frameworks/laravel/prerequisites/
|
||||
- /guides/frameworks/laravel/production-setup/
|
||||
params:
|
||||
tags: [languages]
|
||||
time: 30 minutes
|
||||
---
|
||||
|
||||
|
||||
Laravel is a popular PHP framework that allows developers to build web applications quickly and effectively. Docker Compose simplifies the management of development and production environments by defining essential services, like PHP, a web server, and a database, in a single YAML file. This guide provides a streamlined approach to setting up a robust Laravel environment using Docker Compose, focusing on simplicity and efficiency.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Sergei Shitikov](https://github.com/rw4lll) for
|
||||
> his contribution to this guide.
|
||||
|
||||
The demonstrated examples can be found in [this GitHub repository](https://github.com/dockersamples/laravel-docker-examples). Docker Compose offers a straightforward approach to connecting multiple containers for Laravel, though similar setups can also be achieved using tools like Docker Swarm, Kubernetes, or individual Docker containers.
|
||||
|
||||
This guide is intended for educational purposes, helping developers adapt and optimize configurations for their specific use cases. Additionally, there are existing tools that support Laravel in containers:
|
||||
|
||||
- [Laravel Sail](https://laravel.com/docs/12.x/sail): An official package for easily starting Laravel in Docker.
|
||||
- [Laradock](https://github.com/laradock/laradock): A community project that helps run Laravel applications in Docker.
|
||||
|
||||
## What you’ll learn
|
||||
|
||||
- How to use Docker Compose to set up a Laravel development and production environment.
|
||||
- Defining services that make Laravel development easier, including PHP-FPM, Nginx, and database containers.
|
||||
- Best practices for managing Laravel environments using containerization.
|
||||
|
||||
## Who’s this for?
|
||||
|
||||
- Developers who work with Laravel and want to streamline environment management.
|
||||
- DevOps engineers seeking efficient ways to manage and deploy Laravel applications.
|
||||
|
||||
## Prerequisites for Setting Up Laravel with Docker Compose
|
||||
|
||||
Before you begin setting up Laravel with Docker Compose, make sure you meet the following prerequisites:
|
||||
|
||||
### Docker and Docker Compose
|
||||
|
||||
You need Docker and Docker Compose installed on your system. Docker allows you to containerize applications, and Docker Compose helps you manage multi-container applications.
|
||||
|
||||
- Docker: Make sure Docker is installed and running on your machine. Refer to the [Docker installation guide](/get-docker/) to install Docker.
|
||||
- Docker Compose: Docker Compose is included with Docker Desktop, but you can also follow the [Docker Compose installation guide](/compose/install/) if needed.
|
||||
|
||||
### Basic understanding of Docker and containers
|
||||
|
||||
A fundamental understanding of Docker and how containers work will be helpful. If you're new to Docker, consider reviewing the [Docker Overview](/get-started/overview/) to familiarize yourself with containerization concepts.
|
||||
|
||||
### Basic knowledge of Laravel
|
||||
|
||||
This guide assumes you have a basic understanding of Laravel and PHP. Familiarity with Laravel’s command-line tools, such as [Artisan](https://laravel.com/docs/12.x/artisan), and its project structure is important for following the instructions.
|
||||
|
||||
- Laravel CLI: You should be comfortable using Laravel’s command-line tool (`artisan`).
|
||||
- Laravel Project Structure: Familiarize yourself with Laravel’s folder structure (`app`, `config`, `routes`, `tests`, etc.).
|
||||
|
||||
## Laravel Production Setup with Docker Compose
|
||||
|
||||
This guide demonstrates how to set up a production-ready Laravel environment using Docker and Docker Compose. This configuration is designed for streamlined, scalable, and secure Laravel application deployments.
|
||||
|
||||
> [!NOTE]
|
||||
> To experiment with a ready-to-run configuration, download the [Laravel Docker Examples](https://github.com/dockersamples/laravel-docker-examples) repository. It contains pre-configured setups for both development and production.
|
||||
|
||||
### Project structure
|
||||
|
||||
```plaintext
|
||||
my-laravel-app/
|
||||
├── app/
|
||||
├── bootstrap/
|
||||
├── config/
|
||||
├── database/
|
||||
├── public/
|
||||
├── docker/
|
||||
│ ├── common/
|
||||
│ │ └── php-fpm/
|
||||
│ │ ├── Dockerfile
|
||||
│ │ └── conf.d/
|
||||
│ │ └── 20-status-path.conf
|
||||
│ ├── development/
|
||||
│ ├── production/
|
||||
│ │ ├── php-fpm/
|
||||
│ │ │ └── entrypoint.sh
|
||||
│ │ └── nginx
|
||||
│ │ ├── Dockerfile
|
||||
│ │ └── nginx.conf
|
||||
├── compose.dev.yaml
|
||||
├── compose.prod.yaml
|
||||
├── .dockerignore
|
||||
├── .env
|
||||
├── vendor/
|
||||
├── ...
|
||||
```
|
||||
|
||||
This layout represents a typical Laravel project, with Docker configurations stored in a unified `docker` directory. You’ll find **two** Compose files — `compose.dev.yaml` (for development) and `compose.prod.yaml` (for production) — to keep your environments separate and manageable.
|
||||
|
||||
### Create a Dockerfile for PHP-FPM (production)
|
||||
|
||||
For production, the `php-fpm` Dockerfile creates an optimized image with only the PHP extensions and libraries your application needs. As demonstrated in the [GitHub example](https://github.com/dockersamples/laravel-docker-examples), a single Dockerfile with multi-stage builds maintains consistency and reduces duplication between development and production. The following snippet shows only the production-related stages:
|
||||
|
||||
```dockerfile
|
||||
# Stage 1: Build environment and Composer dependencies
|
||||
FROM php:8.5-fpm AS builder
|
||||
|
||||
# Install system dependencies and PHP extensions for Laravel with MySQL/PostgreSQL support.
|
||||
# Dependencies in this stage are only required for building the final image.
|
||||
# Node.js and asset building are handled in the Nginx stage, not here.
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
unzip \
|
||||
libpq-dev \
|
||||
libonig-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
pdo_mysql \
|
||||
pdo_pgsql \
|
||||
pgsql \
|
||||
intl \
|
||||
zip \
|
||||
bcmath \
|
||||
soap \
|
||||
&& pecl install redis \
|
||||
&& docker-php-ext-enable redis \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy the entire Laravel application code into the container
|
||||
# -----------------------------------------------------------
|
||||
# In Laravel, `composer install` may trigger scripts
|
||||
# needing access to application code.
|
||||
# For example, the `post-autoload-dump` event might execute
|
||||
# Artisan commands like `php artisan package:discover`. If the
|
||||
# application code (including the `artisan` file) is not
|
||||
# present, these commands will fail, leading to build errors.
|
||||
#
|
||||
# By copying the entire application code before running
|
||||
# `composer install`, we ensure that all necessary files are
|
||||
# available, allowing these scripts to run successfully.
|
||||
# In other cases, it would be possible to copy composer files
|
||||
# first, to leverage Docker's layer caching mechanism.
|
||||
# -----------------------------------------------------------
|
||||
COPY . /var/www
|
||||
|
||||
# Install Composer and dependencies
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
|
||||
&& composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist
|
||||
|
||||
# Stage 2: Production environment
|
||||
FROM php:8.5-fpm AS production
|
||||
|
||||
# Install only runtime libraries needed in production
|
||||
# libfcgi-bin and procps are required for the php-fpm-healthcheck script
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libpq-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
libfcgi-bin \
|
||||
procps \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Download and install php-fpm health check script
|
||||
RUN curl -o /usr/local/bin/php-fpm-healthcheck \
|
||||
https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck \
|
||||
&& chmod +x /usr/local/bin/php-fpm-healthcheck
|
||||
|
||||
# Copy the initialization script
|
||||
COPY ./docker/php-fpm/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
# Copy the initial storage structure
|
||||
COPY ./storage /var/www/storage-init
|
||||
|
||||
# Copy PHP extensions and libraries from the builder stage
|
||||
COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
|
||||
COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
|
||||
COPY --from=builder /usr/local/bin/docker-php-ext-* /usr/local/bin/
|
||||
|
||||
# Use the recommended production PHP configuration
|
||||
# -----------------------------------------------------------
|
||||
# PHP provides development and production configurations.
|
||||
# Here, we replace the default php.ini with the production
|
||||
# version to apply settings optimized for performance and
|
||||
# security in a live environment.
|
||||
# -----------------------------------------------------------
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Keep the image-provided FPM global config intact and add pool overrides separately
|
||||
COPY ./docker/common/php-fpm/conf.d/*.conf /usr/local/etc/php-fpm.d/
|
||||
# Update the variables_order to include E (for ENV)
|
||||
#RUN sed -i 's/variables_order = "GPCS"/variables_order = "EGPCS"/' "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Copy the application code and dependencies from the build stage
|
||||
COPY --from=builder /var/www /var/www
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Ensure correct permissions
|
||||
RUN chown -R www-data:www-data /var/www
|
||||
|
||||
# Switch to the non-privileged user to run the application
|
||||
USER www-data
|
||||
|
||||
# Change the default command to run the entrypoint script
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
# Expose port 9000 and start php-fpm server
|
||||
EXPOSE 9000
|
||||
CMD ["php-fpm"]
|
||||
```
|
||||
|
||||
### Create a Dockerfile for PHP-CLI (production)
|
||||
|
||||
For production, you often need a separate container to run Artisan commands, migrations, and other CLI tasks. In most cases you can run these commands by reusing existing PHP-FPM container:
|
||||
|
||||
```console
|
||||
$ docker compose -f compose.prod.yaml exec php-fpm php artisan route:list
|
||||
```
|
||||
|
||||
If you need a separate CLI container with different extensions or strict separation of concerns, consider a php-cli Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
# Stage 1: Build environment and Composer dependencies
|
||||
FROM php:8.5-cli AS builder
|
||||
|
||||
# Install system dependencies and PHP extensions required for Laravel + MySQL/PostgreSQL support
|
||||
# Some dependencies are required for PHP extensions only in the build stage
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
unzip \
|
||||
libpq-dev \
|
||||
libonig-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
pdo_mysql \
|
||||
pdo_pgsql \
|
||||
pgsql \
|
||||
intl \
|
||||
zip \
|
||||
bcmath \
|
||||
soap \
|
||||
&& pecl install redis \
|
||||
&& docker-php-ext-enable redis \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy the entire Laravel application code into the container
|
||||
COPY . /var/www
|
||||
|
||||
# Install Composer and dependencies
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
|
||||
&& composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist
|
||||
|
||||
# Stage 2: Production environment
|
||||
FROM php:8.5-cli
|
||||
|
||||
# Install client libraries required for php extensions in runtime
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libpq-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Copy PHP extensions and libraries from the builder stage
|
||||
COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
|
||||
COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
|
||||
COPY --from=builder /usr/local/bin/docker-php-ext-* /usr/local/bin/
|
||||
|
||||
# Use the default production configuration for PHP runtime arguments
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Copy the application code and dependencies from the build stage
|
||||
COPY --from=builder /var/www /var/www
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Ensure correct permissions
|
||||
RUN chown -R www-data:www-data /var/www
|
||||
|
||||
# Switch to the non-privileged user to run the application
|
||||
USER www-data
|
||||
|
||||
# Default command: Provide a bash shell to allow running any command
|
||||
CMD ["bash"]
|
||||
```
|
||||
|
||||
This Dockerfile is similar to the PHP-FPM Dockerfile, but it uses the `php:8.5-cli` image as the base image and sets up the container for running CLI commands.
|
||||
|
||||
### Create a Dockerfile for Nginx (production)
|
||||
|
||||
Nginx serves as the web server for the Laravel application. You can include static assets directly to the container. Here's an example of possible Dockerfile for Nginx:
|
||||
|
||||
```dockerfile
|
||||
# docker/nginx/Dockerfile
|
||||
# Stage 1: Build assets
|
||||
FROM debian AS builder
|
||||
|
||||
# Install Node.js and build tools
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
nodejs \
|
||||
npm \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy Laravel application code
|
||||
COPY . /var/www
|
||||
|
||||
# Install Node.js dependencies and build assets
|
||||
RUN npm install && npm run build
|
||||
|
||||
# Stage 2: Nginx production image
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy custom Nginx configuration
|
||||
# -----------------------------------------------------------
|
||||
# Replace the default Nginx configuration with our custom one
|
||||
# that is optimized for serving a Laravel application.
|
||||
# -----------------------------------------------------------
|
||||
COPY ./docker/nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
# Copy Laravel's public assets from the builder stage
|
||||
# -----------------------------------------------------------
|
||||
# We only need the 'public' directory from our Laravel app.
|
||||
# -----------------------------------------------------------
|
||||
COPY --from=builder /var/www/public /var/www/public
|
||||
|
||||
# Set the working directory to the public folder
|
||||
WORKDIR /var/www/public
|
||||
|
||||
# Expose port 80 and start Nginx
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
||||
This Dockerfile uses a multi-stage build to separate the asset building process from the final production image. The first stage installs Node.js and builds the assets, while the second stage sets up the Nginx production image with the optimized configuration and the built assets.
|
||||
|
||||
### Create a Docker Compose configuration for production
|
||||
|
||||
To bring all the services together, create a `compose.prod.yaml` file that defines the services, volumes, and networks for the production environment. Here's an example configuration:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/production/nginx/Dockerfile
|
||||
restart: unless-stopped # Automatically restart unless the service is explicitly stopped
|
||||
volumes:
|
||||
# Mount the 'laravel-storage' volume to '/var/www/storage' inside the container.
|
||||
# -----------------------------------------------------------
|
||||
# This volume stores persistent data like uploaded files and cache.
|
||||
# The ':ro' option mounts it as read-only in the 'web' service because Nginx only needs to read these files.
|
||||
# The 'php-fpm' service mounts the same volume without ':ro' to allow write operations.
|
||||
# -----------------------------------------------------------
|
||||
- laravel-storage-production:/var/www/storage:ro
|
||||
networks:
|
||||
- laravel-production
|
||||
ports:
|
||||
# Map port 80 inside the container to the port specified by 'NGINX_PORT' on the host machine.
|
||||
# -----------------------------------------------------------
|
||||
# This allows external access to the Nginx web server running inside the container.
|
||||
# For example, if 'NGINX_PORT' is set to '8080', accessing 'http://localhost:8080' will reach the application.
|
||||
# -----------------------------------------------------------
|
||||
- "${NGINX_PORT:-80}:80"
|
||||
depends_on:
|
||||
php-fpm:
|
||||
condition: service_healthy # Wait for php-fpm health check
|
||||
|
||||
php-fpm:
|
||||
# For the php-fpm service, we will create a custom image to install the necessary PHP extensions and setup proper permissions.
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/common/php-fpm/Dockerfile
|
||||
target: production # Use the 'production' stage in the Dockerfile
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- laravel-storage-production:/var/www/storage # Mount the storage volume
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- laravel-production
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "php-fpm-healthcheck || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
# The 'depends_on' attribute with 'condition: service_healthy' ensures that
|
||||
# this service will not start until the 'postgres' service passes its health check.
|
||||
# This prevents the application from trying to connect to the database before it's ready.
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
# The 'php-cli' service provides a command-line interface for running Artisan commands and other CLI tasks.
|
||||
# -----------------------------------------------------------
|
||||
# This is useful for running migrations, seeders, or any custom scripts.
|
||||
# It shares the same codebase and environment as the 'php-fpm' service.
|
||||
# -----------------------------------------------------------
|
||||
php-cli:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/php-cli/Dockerfile
|
||||
tty: true # Enables an interactive terminal
|
||||
stdin_open: true # Keeps standard input open for 'docker exec'
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- laravel-production
|
||||
|
||||
postgres:
|
||||
image: postgres:18
|
||||
restart: unless-stopped
|
||||
user: postgres
|
||||
ports:
|
||||
- "${POSTGRES_PORT}:5432"
|
||||
environment:
|
||||
- POSTGRES_DB=${POSTGRES_DATABASE}
|
||||
- POSTGRES_USER=${POSTGRES_USERNAME}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- postgres-data-production:/var/lib/postgresql
|
||||
networks:
|
||||
- laravel-production
|
||||
# Health check for PostgreSQL
|
||||
# -----------------------------------------------------------
|
||||
# Health checks allow Docker to determine if a service is operational.
|
||||
# The 'pg_isready' command checks if PostgreSQL is ready to accept connections.
|
||||
# This prevents dependent services from starting before the database is ready.
|
||||
# -----------------------------------------------------------
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: unless-stopped # Automatically restart unless the service is explicitly stopped
|
||||
networks:
|
||||
- laravel-production
|
||||
# Health check for Redis
|
||||
# -----------------------------------------------------------
|
||||
# Checks if Redis is responding to the 'PING' command.
|
||||
# This ensures that the service is not only running but also operational.
|
||||
# -----------------------------------------------------------
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
networks:
|
||||
# Attach the service to the 'laravel-production' network.
|
||||
# -----------------------------------------------------------
|
||||
# This custom network allows all services within it to communicate using their service names as hostnames.
|
||||
# For example, 'php-fpm' can connect to 'postgres' by using 'postgres' as the hostname.
|
||||
# -----------------------------------------------------------
|
||||
laravel-production:
|
||||
|
||||
volumes:
|
||||
postgres-data-production:
|
||||
laravel-storage-production:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Ensure you have an `.env` file at the root of your Laravel project with the necessary configurations to match the Docker Compose setup.
|
||||
|
||||
### Running your production environment
|
||||
|
||||
To start the production environment, run:
|
||||
|
||||
```console
|
||||
$ docker compose -f compose.prod.yaml up --build -d
|
||||
```
|
||||
|
||||
This command will build and start all the services in detached mode, providing a scalable and production-ready setup for your Laravel application.
|
||||
|
||||
### Summary
|
||||
|
||||
By setting up a Docker Compose environment for Laravel in production, you ensure that your application is optimized for performance, scalable, and secure. This setup makes deployments consistent and easier to manage, reducing the likelihood of errors due to differences between environments.
|
||||
|
||||
## Laravel Development Setup with Docker Compose
|
||||
|
||||
This guide demonstrates how to configure a **development** environment for a Laravel application using Docker and Docker Compose. It builds **on top of** the production image for PHP-FPM and then adds developer-focused features—like Xdebug—to streamline debugging. By basing the development container on a known production image, you keep both environments closely aligned.
|
||||
|
||||
This setup includes PHP-FPM, Nginx, and PostgreSQL services (although you can easily swap PostgreSQL for another database, like MySQL or MariaDB). Everything runs in containers, so you can develop in isolation without altering your host system.
|
||||
|
||||
> [!NOTE]
|
||||
> To experiment with a ready-to-run configuration, download the [Laravel Docker Examples](https://github.com/dockersamples/laravel-docker-examples) repository. It contains pre-configured setups for both development and production.
|
||||
|
||||
### Project structure
|
||||
|
||||
```plaintext
|
||||
my-laravel-app/
|
||||
├── app/
|
||||
├── bootstrap/
|
||||
├── config/
|
||||
├── database/
|
||||
├── public/
|
||||
├── docker/
|
||||
│ ├── common/
|
||||
│ │ └── php-fpm/
|
||||
│ │ └── Dockerfile
|
||||
│ ├── development/
|
||||
│ │ ├── php-fpm/
|
||||
│ │ │ └── entrypoint.sh
|
||||
│ │ ├── workspace/
|
||||
│ │ │ └── Dockerfile
|
||||
│ │ └── nginx
|
||||
│ │ ├── Dockerfile
|
||||
│ │ └── nginx.conf
|
||||
│ └── production/
|
||||
├── compose.dev.yaml
|
||||
├── compose.prod.yaml
|
||||
├── .dockerignore
|
||||
├── .env
|
||||
├── vendor/
|
||||
├── ...
|
||||
```
|
||||
|
||||
This layout represents a typical Laravel project, with Docker configurations stored in a unified `docker` directory. You’ll find **two** Compose files — `compose.dev.yaml` (for development) and `compose.prod.yaml` (for production) — to keep your environments separate and manageable.
|
||||
|
||||
The environment includes a `workspace` service, a sidecar container for tasks like building front-end assets, running Artisan commands, and other CLI tools your project may require. While this extra container may seem unusual, it’s a familiar pattern in solutions like **Laravel Sail** and **Laradock**. It also includes **Xdebug** to aid in debugging.
|
||||
|
||||
### Create a Dockerfile for PHP-FPM
|
||||
|
||||
This Dockerfile **extends** the production image by installing Xdebug and adjusting user permissions to ease local development. That way, your development environment stays consistent with production while still offering extra debug features and improved file mounting.
|
||||
|
||||
```dockerfile
|
||||
# Builds a dev-only layer on top of the production image
|
||||
FROM production AS development
|
||||
|
||||
# Use ARGs to define environment variables passed from the Docker build command or Docker Compose.
|
||||
ARG XDEBUG_ENABLED=true
|
||||
ARG XDEBUG_MODE=develop,coverage,debug,profile
|
||||
ARG XDEBUG_HOST=host.docker.internal
|
||||
ARG XDEBUG_IDE_KEY=DOCKER
|
||||
ARG XDEBUG_LOG=/dev/stdout
|
||||
ARG XDEBUG_LOG_LEVEL=0
|
||||
|
||||
USER root
|
||||
|
||||
# Configure Xdebug if enabled
|
||||
RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \
|
||||
pecl install xdebug && \
|
||||
docker-php-ext-enable xdebug && \
|
||||
echo "xdebug.mode=${XDEBUG_MODE}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.idekey=${XDEBUG_IDE_KEY}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log=${XDEBUG_LOG}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.client_host=${XDEBUG_HOST}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
fi
|
||||
|
||||
# Add ARGs for syncing permissions
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
|
||||
# Create a new user with the specified UID and GID, reusing an existing group if GID exists
|
||||
RUN if getent group ${GID}; then \
|
||||
group_name=$(getent group ${GID} | cut -d: -f1); \
|
||||
useradd -m -u ${UID} -g ${GID} -s /bin/bash www; \
|
||||
else \
|
||||
groupadd -g ${GID} www && \
|
||||
useradd -m -u ${UID} -g www -s /bin/bash www; \
|
||||
group_name=www; \
|
||||
fi
|
||||
|
||||
# Dynamically update php-fpm to use the new user and group
|
||||
RUN sed -i "s/user = www-data/user = www/g" /usr/local/etc/php-fpm.d/www.conf && \
|
||||
sed -i "s/group = www-data/group = $group_name/g" /usr/local/etc/php-fpm.d/www.conf
|
||||
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy the entrypoint script
|
||||
COPY ./docker/development/php-fpm/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
# Switch back to the non-privileged user to run the application
|
||||
USER www-data
|
||||
|
||||
# Change the default command to run the entrypoint script
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
# Expose port 9000 and start php-fpm server
|
||||
EXPOSE 9000
|
||||
CMD ["php-fpm"]
|
||||
```
|
||||
|
||||
### Create a Dockerfile for Workspace
|
||||
|
||||
A workspace container provides a dedicated shell for asset compilation, Artisan/Composer commands, and other CLI tasks. This approach follows patterns from Laravel Sail and Laradock, consolidating all development tools into one container for convenience.
|
||||
|
||||
```dockerfile
|
||||
# docker/development/workspace/Dockerfile
|
||||
# Use the official PHP CLI image as the base
|
||||
FROM php:8.5-cli
|
||||
|
||||
# Set environment variables for user and group ID
|
||||
ARG UID=1000
|
||||
ARG GID=1000
|
||||
ARG NODE_VERSION=22.0.0
|
||||
|
||||
# Install system dependencies and build libraries
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
unzip \
|
||||
libpq-dev \
|
||||
libonig-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
pdo_mysql \
|
||||
pdo_pgsql \
|
||||
pgsql \
|
||||
intl \
|
||||
zip \
|
||||
bcmath \
|
||||
soap \
|
||||
&& pecl install redis \
|
||||
&& docker-php-ext-enable redis \
|
||||
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Use ARG to define environment variables passed from the Docker build command or Docker Compose.
|
||||
ARG XDEBUG_ENABLED
|
||||
ARG XDEBUG_MODE
|
||||
ARG XDEBUG_HOST
|
||||
ARG XDEBUG_IDE_KEY
|
||||
ARG XDEBUG_LOG
|
||||
ARG XDEBUG_LOG_LEVEL
|
||||
|
||||
# Configure Xdebug if enabled
|
||||
RUN if [ "${XDEBUG_ENABLED}" = "true" ]; then \
|
||||
pecl install xdebug && \
|
||||
docker-php-ext-enable xdebug && \
|
||||
echo "xdebug.mode=${XDEBUG_MODE}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.idekey=${XDEBUG_IDE_KEY}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log=${XDEBUG_LOG}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.log_level=${XDEBUG_LOG_LEVEL}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini && \
|
||||
echo "xdebug.client_host=${XDEBUG_HOST}" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini ; \
|
||||
fi
|
||||
|
||||
# If the group already exists, use it; otherwise, create the 'www' group
|
||||
RUN if getent group ${GID}; then \
|
||||
useradd -m -u ${UID} -g ${GID} -s /bin/bash www; \
|
||||
else \
|
||||
groupadd -g ${GID} www && \
|
||||
useradd -m -u ${UID} -g www -s /bin/bash www; \
|
||||
fi && \
|
||||
usermod -aG sudo www && \
|
||||
echo 'www ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||
|
||||
# Switch to the non-root user to install NVM and Node.js
|
||||
USER www
|
||||
|
||||
# Install NVM (Node Version Manager) as the www user
|
||||
RUN export NVM_DIR="$HOME/.nvm" && \
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash && \
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" && \
|
||||
nvm install ${NODE_VERSION} && \
|
||||
nvm alias default ${NODE_VERSION} && \
|
||||
nvm use default
|
||||
|
||||
# Ensure NVM is available for all future shells
|
||||
RUN echo 'export NVM_DIR="$HOME/.nvm"' >> /home/www/.bashrc && \
|
||||
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> /home/www/.bashrc && \
|
||||
echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> /home/www/.bashrc
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Override the entrypoint to avoid the default php entrypoint
|
||||
ENTRYPOINT []
|
||||
|
||||
# Default command to keep the container running
|
||||
CMD ["bash"]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you prefer a **one-service-per-container** approach, simply omit the workspace container and run separate containers for each task. For example, you could use a dedicated `php-cli` container for your PHP scripts, and a `node` container to handle the asset building.
|
||||
|
||||
### Create a Docker Compose configuration for development
|
||||
|
||||
Here's the `compose.yaml` file to set up the development environment:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
image: nginx:latest # Using the default Nginx image with custom configuration.
|
||||
volumes:
|
||||
# Mount the application code for live updates
|
||||
- ./:/var/www
|
||||
# Mount the Nginx configuration file
|
||||
- ./docker/development/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
ports:
|
||||
# Map port 80 inside the container to the port specified by 'NGINX_PORT' on the host machine
|
||||
- "80:80"
|
||||
environment:
|
||||
- NGINX_HOST=localhost
|
||||
networks:
|
||||
- laravel-development
|
||||
depends_on:
|
||||
php-fpm:
|
||||
condition: service_started # Wait for php-fpm to start
|
||||
|
||||
php-fpm:
|
||||
# For the php-fpm service, we will use our common PHP-FPM Dockerfile with the development target
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/common/php-fpm/Dockerfile
|
||||
target: development
|
||||
args:
|
||||
UID: ${UID:-1000}
|
||||
GID: ${GID:-1000}
|
||||
XDEBUG_ENABLED: ${XDEBUG_ENABLED:-true}
|
||||
XDEBUG_MODE: develop,coverage,debug,profile
|
||||
XDEBUG_HOST: ${XDEBUG_HOST:-host.docker.internal}
|
||||
XDEBUG_IDE_KEY: ${XDEBUG_IDE_KEY:-DOCKER}
|
||||
XDEBUG_LOG: /dev/stdout
|
||||
XDEBUG_LOG_LEVEL: 0
|
||||
env_file:
|
||||
# Load the environment variables from the Laravel application
|
||||
- .env
|
||||
user: "${UID:-1000}:${GID:-1000}"
|
||||
volumes:
|
||||
# Mount the application code for live updates
|
||||
- ./:/var/www
|
||||
networks:
|
||||
- laravel-development
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_started # Wait for postgres to start
|
||||
|
||||
workspace:
|
||||
# For the workspace service, we will also create a custom image to install and setup all the necessary stuff.
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/development/workspace/Dockerfile
|
||||
args:
|
||||
UID: ${UID:-1000}
|
||||
GID: ${GID:-1000}
|
||||
XDEBUG_ENABLED: ${XDEBUG_ENABLED:-true}
|
||||
XDEBUG_MODE: develop,coverage,debug,profile
|
||||
XDEBUG_HOST: ${XDEBUG_HOST:-host.docker.internal}
|
||||
XDEBUG_IDE_KEY: ${XDEBUG_IDE_KEY:-DOCKER}
|
||||
XDEBUG_LOG: /dev/stdout
|
||||
XDEBUG_LOG_LEVEL: 0
|
||||
tty: true # Enables an interactive terminal
|
||||
stdin_open: true # Keeps standard input open for 'docker exec'
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- ./:/var/www
|
||||
networks:
|
||||
- laravel-development
|
||||
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- "${POSTGRES_PORT:-5432}:5432"
|
||||
environment:
|
||||
- POSTGRES_DB=app
|
||||
- POSTGRES_USER=laravel
|
||||
- POSTGRES_PASSWORD=secret
|
||||
volumes:
|
||||
- postgres-data-development:/var/lib/postgresql
|
||||
networks:
|
||||
- laravel-development
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
networks:
|
||||
- laravel-development
|
||||
|
||||
networks:
|
||||
laravel-development:
|
||||
|
||||
volumes:
|
||||
postgres-data-development:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Ensure you have an `.env` file at the root of your Laravel project with the necessary configurations. You can use the `.env.example` file as a template.
|
||||
|
||||
### Run your development environment
|
||||
|
||||
To start the development environment, use:
|
||||
|
||||
```console
|
||||
$ docker compose -f compose.dev.yaml up --build -d
|
||||
```
|
||||
|
||||
Run this command to build and start the development environment in detached mode. When the containers finish initializing, visit [http://localhost/](http://localhost/) to see your Laravel app in action.
|
||||
|
||||
### Summary
|
||||
|
||||
By building on top of the production image and adding debug tools like Xdebug, you create a Laravel development workflow that closely mirrors production. The optional workspace container simplifies tasks like asset building and running Artisan commands. If you prefer a separate container for every service (e.g., a dedicated `php-cli` and `node` container), you can skip the workspace approach. Either way, Docker Compose provides an efficient, consistent way to develop your Laravel project.
|
||||
|
||||
## Common Questions on Using Laravel with Docker
|
||||
|
||||
<!-- vale Docker.HeadingLength = NO -->
|
||||
|
||||
### 1. Why should I use Docker Compose for Laravel?
|
||||
|
||||
Docker Compose is a powerful tool for managing multi-container environments, particularly in development due to its simplicity. With Docker Compose, you can define and connect all necessary services for Laravel, such as PHP, Nginx, and databases, in a single configuration (`compose.*.yaml`). This setup ensures consistency across development, testing, and production environments, streamlining onboarding and reducing discrepancies between local and server setups.
|
||||
|
||||
While Docker Compose is a great choice for development, tools like **Docker Swarm** or **Kubernetes** offer advanced scaling and orchestration features, which may be beneficial for complex production deployments.
|
||||
|
||||
### 2. How do I debug my Laravel application with Docker Compose?
|
||||
|
||||
To debug your Laravel application in a Docker environment, use **Xdebug**. In the development setup, Xdebug is installed in the `php-fpm` container to enable debugging. Ensure Xdebug is enabled in your `compose.dev.yaml` file by setting the environment variable `XDEBUG_ENABLED=true` and configuring your IDE (e.g., Visual Studio Code or PHPStorm) to connect to the remote container for debugging.
|
||||
|
||||
### 3. Can I use Docker Compose with databases other than PostgreSQL?
|
||||
|
||||
Yes, Docker Compose supports various database services for Laravel. While PostgreSQL is used in the examples, you can easily substitute **MySQL**, **MariaDB**, or even **SQLite**. Update the `compose.*.yaml` file to specify the required Docker image and adjust your `.env` file to reflect the new database configuration.
|
||||
|
||||
### 4. How can I persist data in development and production?
|
||||
|
||||
In both development and production, Docker volumes are used to persist data. For instance, in the `compose.*.yaml` file, the `postgres-data-*` volume stores PostgreSQL data, ensuring that data is retained even if the container restarts. You can also define named volumes for other services where data persistence is essential.
|
||||
|
||||
### 5. What is the difference between development and production Docker configurations?
|
||||
|
||||
In a development environment, Docker configurations include tools that streamline coding and debugging, such as Xdebug for debugging, and volume mounts to enable real-time code updates without requiring image rebuilds.
|
||||
|
||||
In production, the configuration is optimized for performance, security, and efficiency. This setup uses multi-stage builds to keep the image lightweight and includes only essential tools, packages, and libraries.
|
||||
|
||||
It’s recommended to use `alpine`-based images in production for smaller image sizes, enhancing deployment speed and security.
|
||||
|
||||
Additionally, consider using [Docker Scout](/manuals/scout/_index.md) to detect and analyze vulnerabilities, especially in production environments.
|
||||
|
||||
For additional information about using Docker Compose in production, see [this guide](/compose/how-tos/production/).
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
title: Prerequisites for Setting Up Laravel with Docker Compose
|
||||
description: Ensure you have the required tools and knowledge before setting up Laravel with Docker Compose.
|
||||
keywords: laravel, php, docker compose, prerequisites, requirements, setup
|
||||
weight: 10
|
||||
---
|
||||
|
||||
Before you begin setting up Laravel with Docker Compose, make sure you meet the following prerequisites:
|
||||
|
||||
## Docker and Docker Compose
|
||||
|
||||
You need Docker and Docker Compose installed on your system. Docker allows you to containerize applications, and Docker Compose helps you manage multi-container applications.
|
||||
|
||||
- Docker: Make sure Docker is installed and running on your machine. Refer to the [Docker installation guide](/get-docker/) to install Docker.
|
||||
- Docker Compose: Docker Compose is included with Docker Desktop, but you can also follow the [Docker Compose installation guide](/compose/install/) if needed.
|
||||
|
||||
## Basic understanding of Docker and containers
|
||||
|
||||
A fundamental understanding of Docker and how containers work will be helpful. If you're new to Docker, consider reviewing the [Docker Overview](/get-started/overview/) to familiarize yourself with containerization concepts.
|
||||
|
||||
## Basic knowledge of Laravel
|
||||
|
||||
This guide assumes you have a basic understanding of Laravel and PHP. Familiarity with Laravel’s command-line tools, such as [Artisan](https://laravel.com/docs/12.x/artisan), and its project structure is important for following the instructions.
|
||||
|
||||
- Laravel CLI: You should be comfortable using Laravel’s command-line tool (`artisan`).
|
||||
- Laravel Project Structure: Familiarize yourself with Laravel’s folder structure (`app`, `config`, `routes`, `tests`, etc.).
|
||||
@@ -1,444 +0,0 @@
|
||||
---
|
||||
title: Laravel Production Setup with Docker Compose
|
||||
description: Set up a production-ready environment for Laravel using Docker Compose.
|
||||
keywords: laravel, php, docker compose, production, deployment, php-fpm
|
||||
weight: 20
|
||||
---
|
||||
|
||||
This guide demonstrates how to set up a production-ready Laravel environment using Docker and Docker Compose. This configuration is designed for streamlined, scalable, and secure Laravel application deployments.
|
||||
|
||||
> [!NOTE]
|
||||
> To experiment with a ready-to-run configuration, download the [Laravel Docker Examples](https://github.com/dockersamples/laravel-docker-examples) repository. It contains pre-configured setups for both development and production.
|
||||
|
||||
## Project structure
|
||||
|
||||
```plaintext
|
||||
my-laravel-app/
|
||||
├── app/
|
||||
├── bootstrap/
|
||||
├── config/
|
||||
├── database/
|
||||
├── public/
|
||||
├── docker/
|
||||
│ ├── common/
|
||||
│ │ └── php-fpm/
|
||||
│ │ ├── Dockerfile
|
||||
│ │ └── conf.d/
|
||||
│ │ └── 20-status-path.conf
|
||||
│ ├── development/
|
||||
│ ├── production/
|
||||
│ │ ├── php-fpm/
|
||||
│ │ │ └── entrypoint.sh
|
||||
│ │ └── nginx
|
||||
│ │ ├── Dockerfile
|
||||
│ │ └── nginx.conf
|
||||
├── compose.dev.yaml
|
||||
├── compose.prod.yaml
|
||||
├── .dockerignore
|
||||
├── .env
|
||||
├── vendor/
|
||||
├── ...
|
||||
```
|
||||
|
||||
This layout represents a typical Laravel project, with Docker configurations stored in a unified `docker` directory. You’ll find **two** Compose files — `compose.dev.yaml` (for development) and `compose.prod.yaml` (for production) — to keep your environments separate and manageable.
|
||||
|
||||
## Create a Dockerfile for PHP-FPM (production)
|
||||
|
||||
For production, the `php-fpm` Dockerfile creates an optimized image with only the PHP extensions and libraries your application needs. As demonstrated in the [GitHub example](https://github.com/dockersamples/laravel-docker-examples), a single Dockerfile with multi-stage builds maintains consistency and reduces duplication between development and production. The following snippet shows only the production-related stages:
|
||||
|
||||
```dockerfile
|
||||
# Stage 1: Build environment and Composer dependencies
|
||||
FROM php:8.5-fpm AS builder
|
||||
|
||||
# Install system dependencies and PHP extensions for Laravel with MySQL/PostgreSQL support.
|
||||
# Dependencies in this stage are only required for building the final image.
|
||||
# Node.js and asset building are handled in the Nginx stage, not here.
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
unzip \
|
||||
libpq-dev \
|
||||
libonig-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
pdo_mysql \
|
||||
pdo_pgsql \
|
||||
pgsql \
|
||||
intl \
|
||||
zip \
|
||||
bcmath \
|
||||
soap \
|
||||
&& pecl install redis \
|
||||
&& docker-php-ext-enable redis \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy the entire Laravel application code into the container
|
||||
# -----------------------------------------------------------
|
||||
# In Laravel, `composer install` may trigger scripts
|
||||
# needing access to application code.
|
||||
# For example, the `post-autoload-dump` event might execute
|
||||
# Artisan commands like `php artisan package:discover`. If the
|
||||
# application code (including the `artisan` file) is not
|
||||
# present, these commands will fail, leading to build errors.
|
||||
#
|
||||
# By copying the entire application code before running
|
||||
# `composer install`, we ensure that all necessary files are
|
||||
# available, allowing these scripts to run successfully.
|
||||
# In other cases, it would be possible to copy composer files
|
||||
# first, to leverage Docker's layer caching mechanism.
|
||||
# -----------------------------------------------------------
|
||||
COPY . /var/www
|
||||
|
||||
# Install Composer and dependencies
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
|
||||
&& composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist
|
||||
|
||||
# Stage 2: Production environment
|
||||
FROM php:8.5-fpm AS production
|
||||
|
||||
# Install only runtime libraries needed in production
|
||||
# libfcgi-bin and procps are required for the php-fpm-healthcheck script
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libpq-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
libfcgi-bin \
|
||||
procps \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Download and install php-fpm health check script
|
||||
RUN curl -o /usr/local/bin/php-fpm-healthcheck \
|
||||
https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck \
|
||||
&& chmod +x /usr/local/bin/php-fpm-healthcheck
|
||||
|
||||
# Copy the initialization script
|
||||
COPY ./docker/php-fpm/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
|
||||
# Copy the initial storage structure
|
||||
COPY ./storage /var/www/storage-init
|
||||
|
||||
# Copy PHP extensions and libraries from the builder stage
|
||||
COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
|
||||
COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
|
||||
COPY --from=builder /usr/local/bin/docker-php-ext-* /usr/local/bin/
|
||||
|
||||
# Use the recommended production PHP configuration
|
||||
# -----------------------------------------------------------
|
||||
# PHP provides development and production configurations.
|
||||
# Here, we replace the default php.ini with the production
|
||||
# version to apply settings optimized for performance and
|
||||
# security in a live environment.
|
||||
# -----------------------------------------------------------
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Keep the image-provided FPM global config intact and add pool overrides separately
|
||||
COPY ./docker/common/php-fpm/conf.d/*.conf /usr/local/etc/php-fpm.d/
|
||||
# Update the variables_order to include E (for ENV)
|
||||
#RUN sed -i 's/variables_order = "GPCS"/variables_order = "EGPCS"/' "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Copy the application code and dependencies from the build stage
|
||||
COPY --from=builder /var/www /var/www
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Ensure correct permissions
|
||||
RUN chown -R www-data:www-data /var/www
|
||||
|
||||
# Switch to the non-privileged user to run the application
|
||||
USER www-data
|
||||
|
||||
# Change the default command to run the entrypoint script
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
|
||||
# Expose port 9000 and start php-fpm server
|
||||
EXPOSE 9000
|
||||
CMD ["php-fpm"]
|
||||
```
|
||||
|
||||
## Create a Dockerfile for PHP-CLI (production)
|
||||
|
||||
For production, you often need a separate container to run Artisan commands, migrations, and other CLI tasks. In most cases you can run these commands by reusing existing PHP-FPM container:
|
||||
|
||||
```console
|
||||
$ docker compose -f compose.prod.yaml exec php-fpm php artisan route:list
|
||||
```
|
||||
|
||||
If you need a separate CLI container with different extensions or strict separation of concerns, consider a php-cli Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
# Stage 1: Build environment and Composer dependencies
|
||||
FROM php:8.5-cli AS builder
|
||||
|
||||
# Install system dependencies and PHP extensions required for Laravel + MySQL/PostgreSQL support
|
||||
# Some dependencies are required for PHP extensions only in the build stage
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
unzip \
|
||||
libpq-dev \
|
||||
libonig-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& docker-php-ext-install -j$(nproc) \
|
||||
pdo_mysql \
|
||||
pdo_pgsql \
|
||||
pgsql \
|
||||
intl \
|
||||
zip \
|
||||
bcmath \
|
||||
soap \
|
||||
&& pecl install redis \
|
||||
&& docker-php-ext-enable redis \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy the entire Laravel application code into the container
|
||||
COPY . /var/www
|
||||
|
||||
# Install Composer and dependencies
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
|
||||
&& composer install --no-dev --optimize-autoloader --no-interaction --no-progress --prefer-dist
|
||||
|
||||
# Stage 2: Production environment
|
||||
FROM php:8.5-cli
|
||||
|
||||
# Install client libraries required for php extensions in runtime
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libpq-dev \
|
||||
libicu-dev \
|
||||
libzip-dev \
|
||||
&& apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Copy PHP extensions and libraries from the builder stage
|
||||
COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
|
||||
COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
|
||||
COPY --from=builder /usr/local/bin/docker-php-ext-* /usr/local/bin/
|
||||
|
||||
# Use the default production configuration for PHP runtime arguments
|
||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||
|
||||
# Copy the application code and dependencies from the build stage
|
||||
COPY --from=builder /var/www /var/www
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Ensure correct permissions
|
||||
RUN chown -R www-data:www-data /var/www
|
||||
|
||||
# Switch to the non-privileged user to run the application
|
||||
USER www-data
|
||||
|
||||
# Default command: Provide a bash shell to allow running any command
|
||||
CMD ["bash"]
|
||||
```
|
||||
|
||||
This Dockerfile is similar to the PHP-FPM Dockerfile, but it uses the `php:8.5-cli` image as the base image and sets up the container for running CLI commands.
|
||||
|
||||
## Create a Dockerfile for Nginx (production)
|
||||
|
||||
Nginx serves as the web server for the Laravel application. You can include static assets directly to the container. Here's an example of possible Dockerfile for Nginx:
|
||||
|
||||
```dockerfile
|
||||
# docker/nginx/Dockerfile
|
||||
# Stage 1: Build assets
|
||||
FROM debian AS builder
|
||||
|
||||
# Install Node.js and build tools
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
nodejs \
|
||||
npm \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /var/www
|
||||
|
||||
# Copy Laravel application code
|
||||
COPY . /var/www
|
||||
|
||||
# Install Node.js dependencies and build assets
|
||||
RUN npm install && npm run build
|
||||
|
||||
# Stage 2: Nginx production image
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy custom Nginx configuration
|
||||
# -----------------------------------------------------------
|
||||
# Replace the default Nginx configuration with our custom one
|
||||
# that is optimized for serving a Laravel application.
|
||||
# -----------------------------------------------------------
|
||||
COPY ./docker/nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
# Copy Laravel's public assets from the builder stage
|
||||
# -----------------------------------------------------------
|
||||
# We only need the 'public' directory from our Laravel app.
|
||||
# -----------------------------------------------------------
|
||||
COPY --from=builder /var/www/public /var/www/public
|
||||
|
||||
# Set the working directory to the public folder
|
||||
WORKDIR /var/www/public
|
||||
|
||||
# Expose port 80 and start Nginx
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
||||
This Dockerfile uses a multi-stage build to separate the asset building process from the final production image. The first stage installs Node.js and builds the assets, while the second stage sets up the Nginx production image with the optimized configuration and the built assets.
|
||||
|
||||
## Create a Docker Compose configuration for production
|
||||
|
||||
To bring all the services together, create a `compose.prod.yaml` file that defines the services, volumes, and networks for the production environment. Here's an example configuration:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/production/nginx/Dockerfile
|
||||
restart: unless-stopped # Automatically restart unless the service is explicitly stopped
|
||||
volumes:
|
||||
# Mount the 'laravel-storage' volume to '/var/www/storage' inside the container.
|
||||
# -----------------------------------------------------------
|
||||
# This volume stores persistent data like uploaded files and cache.
|
||||
# The ':ro' option mounts it as read-only in the 'web' service because Nginx only needs to read these files.
|
||||
# The 'php-fpm' service mounts the same volume without ':ro' to allow write operations.
|
||||
# -----------------------------------------------------------
|
||||
- laravel-storage-production:/var/www/storage:ro
|
||||
networks:
|
||||
- laravel-production
|
||||
ports:
|
||||
# Map port 80 inside the container to the port specified by 'NGINX_PORT' on the host machine.
|
||||
# -----------------------------------------------------------
|
||||
# This allows external access to the Nginx web server running inside the container.
|
||||
# For example, if 'NGINX_PORT' is set to '8080', accessing 'http://localhost:8080' will reach the application.
|
||||
# -----------------------------------------------------------
|
||||
- "${NGINX_PORT:-80}:80"
|
||||
depends_on:
|
||||
php-fpm:
|
||||
condition: service_healthy # Wait for php-fpm health check
|
||||
|
||||
php-fpm:
|
||||
# For the php-fpm service, we will create a custom image to install the necessary PHP extensions and setup proper permissions.
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/common/php-fpm/Dockerfile
|
||||
target: production # Use the 'production' stage in the Dockerfile
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- laravel-storage-production:/var/www/storage # Mount the storage volume
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- laravel-production
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "php-fpm-healthcheck || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
# The 'depends_on' attribute with 'condition: service_healthy' ensures that
|
||||
# this service will not start until the 'postgres' service passes its health check.
|
||||
# This prevents the application from trying to connect to the database before it's ready.
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
# The 'php-cli' service provides a command-line interface for running Artisan commands and other CLI tasks.
|
||||
# -----------------------------------------------------------
|
||||
# This is useful for running migrations, seeders, or any custom scripts.
|
||||
# It shares the same codebase and environment as the 'php-fpm' service.
|
||||
# -----------------------------------------------------------
|
||||
php-cli:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/php-cli/Dockerfile
|
||||
tty: true # Enables an interactive terminal
|
||||
stdin_open: true # Keeps standard input open for 'docker exec'
|
||||
env_file:
|
||||
- .env
|
||||
networks:
|
||||
- laravel-production
|
||||
|
||||
postgres:
|
||||
image: postgres:18
|
||||
restart: unless-stopped
|
||||
user: postgres
|
||||
ports:
|
||||
- "${POSTGRES_PORT}:5432"
|
||||
environment:
|
||||
- POSTGRES_DB=${POSTGRES_DATABASE}
|
||||
- POSTGRES_USER=${POSTGRES_USERNAME}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- postgres-data-production:/var/lib/postgresql
|
||||
networks:
|
||||
- laravel-production
|
||||
# Health check for PostgreSQL
|
||||
# -----------------------------------------------------------
|
||||
# Health checks allow Docker to determine if a service is operational.
|
||||
# The 'pg_isready' command checks if PostgreSQL is ready to accept connections.
|
||||
# This prevents dependent services from starting before the database is ready.
|
||||
# -----------------------------------------------------------
|
||||
healthcheck:
|
||||
test: ["CMD", "pg_isready"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: unless-stopped # Automatically restart unless the service is explicitly stopped
|
||||
networks:
|
||||
- laravel-production
|
||||
# Health check for Redis
|
||||
# -----------------------------------------------------------
|
||||
# Checks if Redis is responding to the 'PING' command.
|
||||
# This ensures that the service is not only running but also operational.
|
||||
# -----------------------------------------------------------
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
networks:
|
||||
# Attach the service to the 'laravel-production' network.
|
||||
# -----------------------------------------------------------
|
||||
# This custom network allows all services within it to communicate using their service names as hostnames.
|
||||
# For example, 'php-fpm' can connect to 'postgres' by using 'postgres' as the hostname.
|
||||
# -----------------------------------------------------------
|
||||
laravel-production:
|
||||
|
||||
volumes:
|
||||
postgres-data-production:
|
||||
laravel-storage-production:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Ensure you have an `.env` file at the root of your Laravel project with the necessary configurations to match the Docker Compose setup.
|
||||
|
||||
## Running your production environment
|
||||
|
||||
To start the production environment, run:
|
||||
|
||||
```console
|
||||
$ docker compose -f compose.prod.yaml up --build -d
|
||||
```
|
||||
|
||||
This command will build and start all the services in detached mode, providing a scalable and production-ready setup for your Laravel application.
|
||||
|
||||
## Summary
|
||||
|
||||
By setting up a Docker Compose environment for Laravel in production, you ensure that your application is optimized for performance, scalable, and secure. This setup makes deployments consistent and easier to manage, reducing the likelihood of errors due to differences between environments.
|
||||
@@ -5,10 +5,10 @@ title: Generate Docker Compose Files with Claude Code and Docker MCP Toolkit
|
||||
summary: |
|
||||
This guide shows how to wire Claude Code to the Docker MCP Toolkit so it can search Docker Hub images and generate complete Docker Compose stacks from natural language.
|
||||
You’ll enable the Docker Hub MCP server, connect Claude Code, verify MCP access, and create a Node.js + PostgreSQL stack with a conversational prompt.
|
||||
tags: [ai]
|
||||
aliases:
|
||||
- /guides/use-case/genai-claude-code-mcp/
|
||||
params:
|
||||
tags: [ai]
|
||||
time: 15 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ description: This guide walks through the process of setting up and utilizing a
|
||||
keywords: Docker, GenAI, Retrieval-Augmented Generation, RAG, Graph Databases, Neo4j, AI, LLM
|
||||
summary: |
|
||||
This guide explains setting up a GenAI stack with Retrieval-Augmented Generation (RAG) and Neo4j, covering key concepts, deployment steps, and a case study. It also includes troubleshooting tips for optimizing AI performance with real-time data.
|
||||
tags: [ai]
|
||||
params:
|
||||
tags: [ai]
|
||||
time: 35 minutes
|
||||
---
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
title: PDF analysis and chat
|
||||
description: Containerize generative AI (GenAI) apps using Docker
|
||||
keywords: python, generative ai, genai, llm, neo4j, ollama, langchain
|
||||
summary: |
|
||||
Learn how to build a PDF bot for parsing PDF documents and generating
|
||||
responses using Docker and generative AI.
|
||||
tags: [ai]
|
||||
aliases:
|
||||
- /guides/use-case/genai-pdf-bot/
|
||||
params:
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
The generative AI (GenAI) guide teaches you how to containerize an existing GenAI application using Docker. In this guide, you’ll learn how to:
|
||||
|
||||
- Containerize and run a Python-based GenAI application
|
||||
- Set up a local environment to run the complete GenAI stack locally for development
|
||||
|
||||
Start by containerizing an existing GenAI application.
|
||||
@@ -1,264 +0,0 @@
|
||||
---
|
||||
title: Containerize a generative AI application
|
||||
linkTitle: Containerize your app
|
||||
weight: 10
|
||||
keywords: python, generative ai, genai, llm, neo4j, ollama, containerize, initialize, langchain, openai
|
||||
description: Learn how to containerize a generative AI (GenAI) application.
|
||||
aliases:
|
||||
- /guides/use-case/genai-pdf-bot/containerize/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> GenAI applications can often benefit from GPU acceleration. Currently Docker Desktop supports GPU acceleration only on [Windows with the WSL2 backend](/manuals/desktop/features/gpu.md#using-nvidia-gpus-with-wsl2). Linux users can also access GPU acceleration using a native installation of the [Docker Engine](/manuals/engine/install/_index.md).
|
||||
|
||||
- You have installed the latest version of [Docker Desktop](/get-started/get-docker.md) or, if you are a Linux user and are planning to use GPU acceleration, [Docker Engine](/manuals/engine/install/_index.md). Docker adds new features regularly and some parts of this guide may work only with the latest version of Docker Desktop.
|
||||
- You have a [git client](https://git-scm.com/downloads). The examples in this section use a command-line based git client, but you can use any client.
|
||||
|
||||
## Overview
|
||||
|
||||
This section walks you through containerizing a generative AI (GenAI) application using Docker Desktop.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> You can see more samples of containerized GenAI applications in the [GenAI Stack](https://github.com/docker/genai-stack) demo applications.
|
||||
|
||||
## Get the sample application
|
||||
|
||||
The sample application used in this guide is a modified version of the PDF Reader application from the [GenAI Stack](https://github.com/docker/genai-stack) demo applications. The application is a full stack Python application that lets you ask questions about a PDF file.
|
||||
|
||||
The application uses [LangChain](https://www.langchain.com/) for orchestration, [Streamlit](https://streamlit.io/) for the UI, [Ollama](https://ollama.ai/) to run the LLM, and [Neo4j](https://neo4j.com/) to store vectors.
|
||||
|
||||
Clone the sample application. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/craig-osterhout/docker-genai-sample
|
||||
```
|
||||
|
||||
You should now have the following files in your `docker-genai-sample` directory.
|
||||
|
||||
```text
|
||||
├── docker-genai-sample/
|
||||
│ ├── .gitignore
|
||||
│ ├── app.py
|
||||
│ ├── chains.py
|
||||
│ ├── env.example
|
||||
│ ├── requirements.txt
|
||||
│ ├── util.py
|
||||
│ ├── LICENSE
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
## Create Docker assets
|
||||
|
||||
Now that you have an application, you can create the necessary Docker assets to
|
||||
containerize it.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> [Gordon](/ai/gordon/), Docker's AI assistant, can generate Docker assets for your project. Ask Gordon to create a Dockerfile, Compose file, and `.dockerignore` tailored to your application.
|
||||
|
||||
Create the following files in your `docker-genai-sample` directory.
|
||||
|
||||
```dockerfile {collapse=true,title=Dockerfile}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Dockerfile reference guide at
|
||||
# https://docs.docker.com/go/dockerfile-reference/
|
||||
|
||||
ARG PYTHON_VERSION=3.11.4
|
||||
FROM python:${PYTHON_VERSION}-slim as base
|
||||
|
||||
# Prevents Python from writing pyc files.
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# Keeps Python from buffering stdout and stderr to avoid situations where
|
||||
# the application crashes without emitting any logs due to buffering.
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Create a non-privileged user that the app will run under.
|
||||
# See https://docs.docker.com/go/dockerfile-user-best-practices/
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
|
||||
# Download dependencies as a separate step to take advantage of Docker's caching.
|
||||
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
|
||||
# Leverage a bind mount to requirements.txt to avoid having to copy them into
|
||||
# into this layer.
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
--mount=type=bind,source=requirements.txt,target=requirements.txt \
|
||||
python -m pip install -r requirements.txt
|
||||
|
||||
# Switch to the non-privileged user to run the application.
|
||||
USER appuser
|
||||
|
||||
# Copy the source code into the container.
|
||||
COPY . .
|
||||
|
||||
# Expose the port that the application listens on.
|
||||
EXPOSE 8000
|
||||
|
||||
# Run the application.
|
||||
CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0", "--server.port=8000"]
|
||||
```
|
||||
|
||||
```yaml {collapse=true,title=compose.yaml}
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Docker Compose reference guide at
|
||||
# https://docs.docker.com/go/compose-spec-reference/
|
||||
|
||||
# Here the instructions define your application as a service called "server".
|
||||
# This service is built from the Dockerfile in the current directory.
|
||||
# You can add other services your application may depend on here, such as a
|
||||
# database or a cache. For examples, see the Awesome Compose repository:
|
||||
# https://github.com/docker/awesome-compose
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
|
||||
# The commented out section below is an example of how to define a PostgreSQL
|
||||
# database that your application can use. `depends_on` tells Docker Compose to
|
||||
# start the database before your application. The `db-data` volume persists the
|
||||
# database data between container restarts. The `db-password` secret is used
|
||||
# to set the database password. You must create `db/password.txt` and add
|
||||
# a password of your choosing to it before running `docker compose up`.
|
||||
# depends_on:
|
||||
# db:
|
||||
# condition: service_healthy
|
||||
# db:
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# user: postgres
|
||||
# secrets:
|
||||
# - db-password
|
||||
# volumes:
|
||||
# - db-data:/var/lib/postgresql/data
|
||||
# environment:
|
||||
# - POSTGRES_DB=example
|
||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
# expose:
|
||||
# - 5432
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "pg_isready" ]
|
||||
# interval: 10s
|
||||
# timeout: 5s
|
||||
# retries: 5
|
||||
# volumes:
|
||||
# db-data:
|
||||
# secrets:
|
||||
# db-password:
|
||||
# file: db/password.txt
|
||||
```
|
||||
|
||||
```text {collapse=true,title=".dockerignore"}
|
||||
# Include any files or directories that you don't want to be copied to your
|
||||
# container here (e.g., local build artifacts, temporary files, etc.).
|
||||
#
|
||||
# For more help, visit the .dockerignore file reference guide at
|
||||
# https://docs.docker.com/go/build-context-dockerignore/
|
||||
|
||||
**/.DS_Store
|
||||
**/__pycache__
|
||||
**/.venv
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/compose.y*ml
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
```
|
||||
|
||||
You should now have the following contents in your `docker-genai-sample`
|
||||
directory.
|
||||
|
||||
```text
|
||||
├── docker-genai-sample/
|
||||
│ ├── .dockerignore
|
||||
│ ├── .gitignore
|
||||
│ ├── app.py
|
||||
│ ├── chains.py
|
||||
│ ├── compose.yaml
|
||||
│ ├── env.example
|
||||
│ ├── requirements.txt
|
||||
│ ├── util.py
|
||||
│ ├── Dockerfile
|
||||
│ ├── LICENSE
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
To learn more about these files, see the following:
|
||||
|
||||
- [Dockerfile](../../../reference/dockerfile.md)
|
||||
- [.dockerignore](../../../reference/dockerfile.md#dockerignore-file)
|
||||
- [compose.yaml](/reference/compose-file/_index.md)
|
||||
|
||||
## Run the application
|
||||
|
||||
Inside the `docker-genai-sample` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Docker builds and runs your application. Depending on your network connection, it may take several minutes to download all the dependencies. You'll see a message like the following in the terminal when the application is running.
|
||||
|
||||
```console
|
||||
server-1 | You can now view your Streamlit app in your browser.
|
||||
server-1 |
|
||||
server-1 | URL: http://0.0.0.0:8000
|
||||
server-1 |
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8000](http://localhost:8000). You should see a simple Streamlit application. The application may take a few minutes to download the embedding model. While the download is in progress, **Running** appears in the top-right corner.
|
||||
|
||||
The application requires a Neo4j database service and an LLM service to
|
||||
function. If you have access to services that you ran outside of Docker, specify
|
||||
the connection information and try it out. If you don't have the services
|
||||
running, continue with this guide to learn how you can run some or all of these
|
||||
services with Docker.
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how you can containerize and run your GenAI
|
||||
application using Docker.
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how you can run your application, database, and LLM service all locally using Docker.
|
||||
@@ -1,261 +0,0 @@
|
||||
---
|
||||
title: Use containers for generative AI development
|
||||
linkTitle: Develop your app
|
||||
weight: 20
|
||||
keywords: python, local, development, generative ai, genai, llm, neo4j, ollama, langchain, openai
|
||||
description: Learn how to develop your generative AI (GenAI) application locally.
|
||||
aliases:
|
||||
- /guides/use-case/genai-pdf-bot/develop/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete [Containerize a generative AI application](containerize.md).
|
||||
|
||||
## Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment to access all the services that your generative AI (GenAI) application needs. This includes:
|
||||
|
||||
- Adding a local database
|
||||
- Adding a local or remote LLM service
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> You can see more samples of containerized GenAI applications in the [GenAI Stack](https://github.com/docker/genai-stack) demo applications.
|
||||
|
||||
## Add a local database
|
||||
|
||||
You can use containers to set up local services, like a database. In this section, you'll update the `compose.yaml` file to define a database service. In addition, you'll specify an environment variables file to load the database connection information rather than manually entering the information every time.
|
||||
|
||||
To run the database service:
|
||||
|
||||
1. In the cloned repository's directory, rename `env.example` file to `.env`.
|
||||
This file contains the environment variables that the containers will use.
|
||||
2. In the cloned repository's directory, open the `compose.yaml` file in an IDE or text editor.
|
||||
3. In the `compose.yaml` file, add the following:
|
||||
|
||||
- Add instructions to run a Neo4j database
|
||||
- Specify the environment file under the server service in order to pass in the environment variables for the connection
|
||||
|
||||
The following is the updated `compose.yaml` file. All comments have been removed.
|
||||
|
||||
```yaml{hl_lines=["7-23"]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
database:
|
||||
image: neo4j:5.11
|
||||
ports:
|
||||
- "7474:7474"
|
||||
- "7687:7687"
|
||||
environment:
|
||||
- NEO4J_AUTH=${NEO4J_USERNAME}/${NEO4J_PASSWORD}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider localhost:7474 || exit 1"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> To learn more about Neo4j, see the [Neo4j Official Docker Image](https://hub.docker.com/_/neo4j).
|
||||
|
||||
4. Run the application. Inside the `docker-genai-sample` directory,
|
||||
run the following command in a terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
5. Access the application. Open a browser and view the application at [http://localhost:8000](http://localhost:8000). You should see a simple Streamlit application. Note that asking questions to a PDF will cause the application to fail because the LLM service specified in the `.env` file isn't running yet.
|
||||
|
||||
6. Stop the application. In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
## Add a local or remote LLM service
|
||||
|
||||
The sample application supports both [Ollama](https://ollama.ai/) and [OpenAI](https://openai.com/). This guide provides instructions for the following scenarios:
|
||||
|
||||
- Run Ollama in a container
|
||||
- Run Ollama outside of a container
|
||||
- Use OpenAI
|
||||
|
||||
While all platforms can use any of the previous scenarios, the performance and
|
||||
GPU support may vary. You can use the following guidelines to help you choose the appropriate option:
|
||||
|
||||
- Run Ollama in a container if you're on Linux, and using a native installation of the Docker Engine, or Windows 10/11, and using Docker Desktop, you
|
||||
have a CUDA-supported GPU, and your system has at least 8 GB of RAM.
|
||||
- Run Ollama outside of a container if you're on an Apple silicon Mac.
|
||||
- Use OpenAI if the previous two scenarios don't apply to you.
|
||||
|
||||
Choose one of the following options for your LLM service.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Run Ollama in a container" >}}
|
||||
|
||||
When running Ollama in a container, you should have a CUDA-supported GPU. While you can run Ollama in a container without a supported GPU, the performance may not be acceptable. Only Linux and Windows 11 support GPU access to containers.
|
||||
|
||||
To run Ollama in a container and provide GPU access:
|
||||
|
||||
1. Install the prerequisites.
|
||||
- For Docker Engine on Linux, install the [NVIDIA Container Toolkit](https://github.com/NVIDIA/nvidia-container-toolkit).
|
||||
- For Docker Desktop on Windows 10/11, install the latest [NVIDIA driver](https://www.nvidia.com/Download/index.aspx) and make sure you are using the [WSL2 backend](/manuals/desktop/features/wsl/_index.md#turn-on-docker-desktop-wsl-2)
|
||||
2. Add the Ollama service and a volume in your `compose.yaml`. The following is
|
||||
the updated `compose.yaml`:
|
||||
|
||||
```yaml {hl_lines=["24-38"]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
database:
|
||||
image: neo4j:5.11
|
||||
ports:
|
||||
- "7474:7474"
|
||||
- "7687:7687"
|
||||
environment:
|
||||
- NEO4J_AUTH=${NEO4J_USERNAME}/${NEO4J_PASSWORD}
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"wget --no-verbose --tries=1 --spider localhost:7474 || exit 1",
|
||||
]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
ollama:
|
||||
image: ollama/ollama:latest
|
||||
ports:
|
||||
- "11434:11434"
|
||||
volumes:
|
||||
- ollama_volume:/root/.ollama
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [gpu]
|
||||
volumes:
|
||||
ollama_volume:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> For more details about the Compose instructions, see [Turn on GPU access with Docker Compose](/manuals/compose/how-tos/gpu-support.md).
|
||||
|
||||
3. Add the ollama-pull service to your `compose.yaml` file. This service uses
|
||||
the `docker/genai:ollama-pull` image, based on the GenAI Stack's
|
||||
[pull_model.Dockerfile](https://github.com/docker/genai-stack/blob/main/pull_model.Dockerfile).
|
||||
The service will automatically pull the model for your Ollama
|
||||
container. The following is the updated section of the `compose.yaml` file:
|
||||
|
||||
```yaml {hl_lines=["12-17"]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
ollama-pull:
|
||||
condition: service_completed_successfully
|
||||
ollama-pull:
|
||||
image: docker/genai:ollama-pull
|
||||
env_file:
|
||||
- .env
|
||||
# ...
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Run Ollama outside of a container" >}}
|
||||
|
||||
To run Ollama outside of a container:
|
||||
|
||||
1. [Install](https://github.com/jmorganca/ollama) and run Ollama on your host
|
||||
machine.
|
||||
2. Update the `OLLAMA_BASE_URL` value in your `.env` file to
|
||||
`http://host.docker.internal:11434`.
|
||||
3. Pull the model to Ollama using the following command.
|
||||
```console
|
||||
$ ollama pull llama2
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Use OpenAI" >}}
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Using OpenAI requires an [OpenAI account](https://platform.openai.com/login). OpenAI is a third-party hosted service and charges may apply.
|
||||
|
||||
1. Update the `LLM` value in your `.env` file to
|
||||
`gpt-3.5`.
|
||||
2. Uncomment and update the `OPENAI_API_KEY` value in your `.env` file to
|
||||
your [OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-api-key).
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Run your GenAI application
|
||||
|
||||
At this point, you have the following services in your Compose file:
|
||||
|
||||
- Server service for your main GenAI application
|
||||
- Database service to store vectors in a Neo4j database
|
||||
- (optional) Ollama service to run the LLM
|
||||
- (optional) Ollama-pull service to automatically pull the model for the Ollama
|
||||
service
|
||||
|
||||
To run all the services, run the following command in your `docker-genai-sample`
|
||||
directory:
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
If your Compose file has the ollama-pull service, it may take several minutes for the ollama-pull service to pull the model. The ollama-pull service will continuously update the console with its status. After pulling the model, the ollama-pull service container will stop and you can access the application.
|
||||
|
||||
Once the application is running, open a browser and access the application at [http://localhost:8000](http://localhost:8000).
|
||||
|
||||
Upload a PDF file, for example the [Docker CLI Cheat Sheet](https://docs.docker.com/get-started/docker_cheatsheet.pdf), and ask a question about the PDF.
|
||||
|
||||
Depending on your system and the LLM service that you chose, it may take several
|
||||
minutes to answer. If you are using Ollama and the performance isn't
|
||||
acceptable, try using OpenAI.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to set up a development environment to provide
|
||||
access all the services that your GenAI application needs.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Dockerfile reference](../../../reference/dockerfile.md)
|
||||
- [Compose file reference](/reference/compose-file/_index.md)
|
||||
- [Ollama Docker image](https://hub.docker.com/r/ollama/ollama)
|
||||
- [Neo4j Official Docker Image](https://hub.docker.com/_/neo4j)
|
||||
- [GenAI Stack demo applications](https://github.com/docker/genai-stack)
|
||||
|
||||
## Next steps
|
||||
|
||||
See samples of more GenAI applications in the [GenAI Stack demo applications](https://github.com/docker/genai-stack).
|
||||
534
content/guides/genai-pdf-bot/index.md
Normal file
534
content/guides/genai-pdf-bot/index.md
Normal file
@@ -0,0 +1,534 @@
|
||||
---
|
||||
title: PDF analysis and chat
|
||||
description: Containerize generative AI (GenAI) apps using Docker
|
||||
keywords: python, generative ai, genai, llm, neo4j, ollama, langchain
|
||||
summary: |
|
||||
Learn how to build a PDF bot for parsing PDF documents and generating
|
||||
responses using Docker and generative AI.
|
||||
aliases:
|
||||
- /guides/use-case/genai-pdf-bot/
|
||||
- /guides/genai-pdf-bot/containerize/
|
||||
- /guides/genai-pdf-bot/develop/
|
||||
params:
|
||||
tags: [ai]
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
|
||||
The generative AI (GenAI) guide teaches you how to containerize an existing GenAI application using Docker. In this guide, you’ll learn how to:
|
||||
|
||||
- Containerize and run a Python-based GenAI application
|
||||
- Set up a local environment to run the complete GenAI stack locally for development
|
||||
|
||||
Start by containerizing an existing GenAI application.
|
||||
|
||||
## Containerize a generative AI application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> GenAI applications can often benefit from GPU acceleration. Currently Docker Desktop supports GPU acceleration only on [Windows with the WSL2 backend](/manuals/desktop/features/gpu.md#using-nvidia-gpus-with-wsl2). Linux users can also access GPU acceleration using a native installation of the [Docker Engine](/manuals/engine/install/_index.md).
|
||||
|
||||
- You have installed the latest version of [Docker Desktop](/get-started/get-docker.md) or, if you are a Linux user and are planning to use GPU acceleration, [Docker Engine](/manuals/engine/install/_index.md). Docker adds new features regularly and some parts of this guide may work only with the latest version of Docker Desktop.
|
||||
- You have a [git client](https://git-scm.com/downloads). The examples in this section use a command-line based git client, but you can use any client.
|
||||
|
||||
### Overview
|
||||
|
||||
This section walks you through containerizing a generative AI (GenAI) application using Docker Desktop.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> You can see more samples of containerized GenAI applications in the [GenAI Stack](https://github.com/docker/genai-stack) demo applications.
|
||||
|
||||
### Get the sample application
|
||||
|
||||
The sample application used in this guide is a modified version of the PDF Reader application from the [GenAI Stack](https://github.com/docker/genai-stack) demo applications. The application is a full stack Python application that lets you ask questions about a PDF file.
|
||||
|
||||
The application uses [LangChain](https://www.langchain.com/) for orchestration, [Streamlit](https://streamlit.io/) for the UI, [Ollama](https://ollama.ai/) to run the LLM, and [Neo4j](https://neo4j.com/) to store vectors.
|
||||
|
||||
Clone the sample application. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/craig-osterhout/docker-genai-sample
|
||||
```
|
||||
|
||||
You should now have the following files in your `docker-genai-sample` directory.
|
||||
|
||||
```text
|
||||
├── docker-genai-sample/
|
||||
│ ├── .gitignore
|
||||
│ ├── app.py
|
||||
│ ├── chains.py
|
||||
│ ├── env.example
|
||||
│ ├── requirements.txt
|
||||
│ ├── util.py
|
||||
│ ├── LICENSE
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
### Create Docker assets
|
||||
|
||||
Now that you have an application, you can create the necessary Docker assets to
|
||||
containerize it.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> [Gordon](/ai/gordon/), Docker's AI assistant, can generate Docker assets for your project. Ask Gordon to create a Dockerfile, Compose file, and `.dockerignore` tailored to your application.
|
||||
|
||||
Create the following files in your `docker-genai-sample` directory.
|
||||
|
||||
```dockerfile {collapse=true,title=Dockerfile}
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Dockerfile reference guide at
|
||||
# https://docs.docker.com/go/dockerfile-reference/
|
||||
|
||||
ARG PYTHON_VERSION=3.11.4
|
||||
FROM python:${PYTHON_VERSION}-slim as base
|
||||
|
||||
# Prevents Python from writing pyc files.
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# Keeps Python from buffering stdout and stderr to avoid situations where
|
||||
# the application crashes without emitting any logs due to buffering.
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Create a non-privileged user that the app will run under.
|
||||
# See https://docs.docker.com/go/dockerfile-user-best-practices/
|
||||
ARG UID=10001
|
||||
RUN adduser \
|
||||
--disabled-password \
|
||||
--gecos "" \
|
||||
--home "/nonexistent" \
|
||||
--shell "/sbin/nologin" \
|
||||
--no-create-home \
|
||||
--uid "${UID}" \
|
||||
appuser
|
||||
|
||||
# Download dependencies as a separate step to take advantage of Docker's caching.
|
||||
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
|
||||
# Leverage a bind mount to requirements.txt to avoid having to copy them into
|
||||
# into this layer.
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
--mount=type=bind,source=requirements.txt,target=requirements.txt \
|
||||
python -m pip install -r requirements.txt
|
||||
|
||||
# Switch to the non-privileged user to run the application.
|
||||
USER appuser
|
||||
|
||||
# Copy the source code into the container.
|
||||
COPY . .
|
||||
|
||||
# Expose the port that the application listens on.
|
||||
EXPOSE 8000
|
||||
|
||||
# Run the application.
|
||||
CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0", "--server.port=8000"]
|
||||
```
|
||||
|
||||
```yaml {collapse=true,title=compose.yaml}
|
||||
# Comments are provided throughout this file to help you get started.
|
||||
# If you need more help, visit the Docker Compose reference guide at
|
||||
# https://docs.docker.com/go/compose-spec-reference/
|
||||
|
||||
# Here the instructions define your application as a service called "server".
|
||||
# This service is built from the Dockerfile in the current directory.
|
||||
# You can add other services your application may depend on here, such as a
|
||||
# database or a cache. For examples, see the Awesome Compose repository:
|
||||
# https://github.com/docker/awesome-compose
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
|
||||
# The commented out section below is an example of how to define a PostgreSQL
|
||||
# database that your application can use. `depends_on` tells Docker Compose to
|
||||
# start the database before your application. The `db-data` volume persists the
|
||||
# database data between container restarts. The `db-password` secret is used
|
||||
# to set the database password. You must create `db/password.txt` and add
|
||||
# a password of your choosing to it before running `docker compose up`.
|
||||
# depends_on:
|
||||
# db:
|
||||
# condition: service_healthy
|
||||
# db:
|
||||
# image: postgres
|
||||
# restart: always
|
||||
# user: postgres
|
||||
# secrets:
|
||||
# - db-password
|
||||
# volumes:
|
||||
# - db-data:/var/lib/postgresql/data
|
||||
# environment:
|
||||
# - POSTGRES_DB=example
|
||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
# expose:
|
||||
# - 5432
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "pg_isready" ]
|
||||
# interval: 10s
|
||||
# timeout: 5s
|
||||
# retries: 5
|
||||
# volumes:
|
||||
# db-data:
|
||||
# secrets:
|
||||
# db-password:
|
||||
# file: db/password.txt
|
||||
```
|
||||
|
||||
```text {collapse=true,title=".dockerignore"}
|
||||
# Include any files or directories that you don't want to be copied to your
|
||||
# container here (e.g., local build artifacts, temporary files, etc.).
|
||||
#
|
||||
# For more help, visit the .dockerignore file reference guide at
|
||||
# https://docs.docker.com/go/build-context-dockerignore/
|
||||
|
||||
**/.DS_Store
|
||||
**/__pycache__
|
||||
**/.venv
|
||||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/compose.y*ml
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
```
|
||||
|
||||
You should now have the following contents in your `docker-genai-sample`
|
||||
directory.
|
||||
|
||||
```text
|
||||
├── docker-genai-sample/
|
||||
│ ├── .dockerignore
|
||||
│ ├── .gitignore
|
||||
│ ├── app.py
|
||||
│ ├── chains.py
|
||||
│ ├── compose.yaml
|
||||
│ ├── env.example
|
||||
│ ├── requirements.txt
|
||||
│ ├── util.py
|
||||
│ ├── Dockerfile
|
||||
│ ├── LICENSE
|
||||
│ └── README.md
|
||||
```
|
||||
|
||||
To learn more about these files, see the following:
|
||||
|
||||
- [Dockerfile](../../../reference/dockerfile.md)
|
||||
- [.dockerignore](../../../reference/dockerfile.md#dockerignore-file)
|
||||
- [compose.yaml](/reference/compose-file/_index.md)
|
||||
|
||||
### Run the application
|
||||
|
||||
Inside the `docker-genai-sample` directory, run the following command in a
|
||||
terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
Docker builds and runs your application. Depending on your network connection, it may take several minutes to download all the dependencies. You'll see a message like the following in the terminal when the application is running.
|
||||
|
||||
```console
|
||||
server-1 | You can now view your Streamlit app in your browser.
|
||||
server-1 |
|
||||
server-1 | URL: http://0.0.0.0:8000
|
||||
server-1 |
|
||||
```
|
||||
|
||||
Open a browser and view the application at [http://localhost:8000](http://localhost:8000). You should see a simple Streamlit application. The application may take a few minutes to download the embedding model. While the download is in progress, **Running** appears in the top-right corner.
|
||||
|
||||
The application requires a Neo4j database service and an LLM service to
|
||||
function. If you have access to services that you ran outside of Docker, specify
|
||||
the connection information and try it out. If you don't have the services
|
||||
running, continue with this guide to learn how you can run some or all of these
|
||||
services with Docker.
|
||||
|
||||
In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you learned how you can containerize and run your GenAI
|
||||
application using Docker.
|
||||
|
||||
### Next steps
|
||||
|
||||
In the next section, you'll learn how you can run your application, database, and LLM service all locally using Docker.
|
||||
|
||||
## Use containers for generative AI development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Complete [Containerize a generative AI application](./).
|
||||
|
||||
### Overview
|
||||
|
||||
In this section, you'll learn how to set up a development environment to access all the services that your generative AI (GenAI) application needs. This includes:
|
||||
|
||||
- Adding a local database
|
||||
- Adding a local or remote LLM service
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> You can see more samples of containerized GenAI applications in the [GenAI Stack](https://github.com/docker/genai-stack) demo applications.
|
||||
|
||||
### Add a local database
|
||||
|
||||
You can use containers to set up local services, like a database. In this section, you'll update the `compose.yaml` file to define a database service. In addition, you'll specify an environment variables file to load the database connection information rather than manually entering the information every time.
|
||||
|
||||
To run the database service:
|
||||
|
||||
1. In the cloned repository's directory, rename `env.example` file to `.env`.
|
||||
This file contains the environment variables that the containers will use.
|
||||
2. In the cloned repository's directory, open the `compose.yaml` file in an IDE or text editor.
|
||||
3. In the `compose.yaml` file, add the following:
|
||||
|
||||
- Add instructions to run a Neo4j database
|
||||
- Specify the environment file under the server service in order to pass in the environment variables for the connection
|
||||
|
||||
The following is the updated `compose.yaml` file. All comments have been removed.
|
||||
|
||||
```yaml{hl_lines=["7-23"]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
database:
|
||||
image: neo4j:5.11
|
||||
ports:
|
||||
- "7474:7474"
|
||||
- "7687:7687"
|
||||
environment:
|
||||
- NEO4J_AUTH=${NEO4J_USERNAME}/${NEO4J_PASSWORD}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider localhost:7474 || exit 1"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> To learn more about Neo4j, see the [Neo4j Official Docker Image](https://hub.docker.com/_/neo4j).
|
||||
|
||||
4. Run the application. Inside the `docker-genai-sample` directory,
|
||||
run the following command in a terminal.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
5. Access the application. Open a browser and view the application at [http://localhost:8000](http://localhost:8000). You should see a simple Streamlit application. Note that asking questions to a PDF will cause the application to fail because the LLM service specified in the `.env` file isn't running yet.
|
||||
|
||||
6. Stop the application. In the terminal, press `ctrl`+`c` to stop the application.
|
||||
|
||||
### Add a local or remote LLM service
|
||||
|
||||
The sample application supports both [Ollama](https://ollama.ai/) and [OpenAI](https://openai.com/). This guide provides instructions for the following scenarios:
|
||||
|
||||
- Run Ollama in a container
|
||||
- Run Ollama outside of a container
|
||||
- Use OpenAI
|
||||
|
||||
While all platforms can use any of the previous scenarios, the performance and
|
||||
GPU support may vary. You can use the following guidelines to help you choose the appropriate option:
|
||||
|
||||
- Run Ollama in a container if you're on Linux, and using a native installation of the Docker Engine, or Windows 10/11, and using Docker Desktop, you
|
||||
have a CUDA-supported GPU, and your system has at least 8 GB of RAM.
|
||||
- Run Ollama outside of a container if you're on an Apple silicon Mac.
|
||||
- Use OpenAI if the previous two scenarios don't apply to you.
|
||||
|
||||
Choose one of the following options for your LLM service.
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Run Ollama in a container" >}}
|
||||
|
||||
When running Ollama in a container, you should have a CUDA-supported GPU. While you can run Ollama in a container without a supported GPU, the performance may not be acceptable. Only Linux and Windows 11 support GPU access to containers.
|
||||
|
||||
To run Ollama in a container and provide GPU access:
|
||||
|
||||
1. Install the prerequisites.
|
||||
- For Docker Engine on Linux, install the [NVIDIA Container Toolkit](https://github.com/NVIDIA/nvidia-container-toolkit).
|
||||
- For Docker Desktop on Windows 10/11, install the latest [NVIDIA driver](https://www.nvidia.com/Download/index.aspx) and make sure you are using the [WSL2 backend](/manuals/desktop/features/wsl/_index.md#turn-on-docker-desktop-wsl-2)
|
||||
2. Add the Ollama service and a volume in your `compose.yaml`. The following is
|
||||
the updated `compose.yaml`:
|
||||
|
||||
```yaml {hl_lines=["24-38"]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
database:
|
||||
image: neo4j:5.11
|
||||
ports:
|
||||
- "7474:7474"
|
||||
- "7687:7687"
|
||||
environment:
|
||||
- NEO4J_AUTH=${NEO4J_USERNAME}/${NEO4J_PASSWORD}
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"wget --no-verbose --tries=1 --spider localhost:7474 || exit 1",
|
||||
]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
ollama:
|
||||
image: ollama/ollama:latest
|
||||
ports:
|
||||
- "11434:11434"
|
||||
volumes:
|
||||
- ollama_volume:/root/.ollama
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: all
|
||||
capabilities: [gpu]
|
||||
volumes:
|
||||
ollama_volume:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> For more details about the Compose instructions, see [Turn on GPU access with Docker Compose](/manuals/compose/how-tos/gpu-support.md).
|
||||
|
||||
3. Add the ollama-pull service to your `compose.yaml` file. This service uses
|
||||
the `docker/genai:ollama-pull` image, based on the GenAI Stack's
|
||||
[pull_model.Dockerfile](https://github.com/docker/genai-stack/blob/main/pull_model.Dockerfile).
|
||||
The service will automatically pull the model for your Ollama
|
||||
container. The following is the updated section of the `compose.yaml` file:
|
||||
|
||||
```yaml {hl_lines=["12-17"]}
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
ports:
|
||||
- 8000:8000
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
database:
|
||||
condition: service_healthy
|
||||
ollama-pull:
|
||||
condition: service_completed_successfully
|
||||
ollama-pull:
|
||||
image: docker/genai:ollama-pull
|
||||
env_file:
|
||||
- .env
|
||||
# ...
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Run Ollama outside of a container" >}}
|
||||
|
||||
To run Ollama outside of a container:
|
||||
|
||||
1. [Install](https://github.com/jmorganca/ollama) and run Ollama on your host
|
||||
machine.
|
||||
2. Update the `OLLAMA_BASE_URL` value in your `.env` file to
|
||||
`http://host.docker.internal:11434`.
|
||||
3. Pull the model to Ollama using the following command.
|
||||
```console
|
||||
$ ollama pull llama2
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Use OpenAI" >}}
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Using OpenAI requires an [OpenAI account](https://platform.openai.com/login). OpenAI is a third-party hosted service and charges may apply.
|
||||
|
||||
1. Update the `LLM` value in your `.env` file to
|
||||
`gpt-3.5`.
|
||||
2. Uncomment and update the `OPENAI_API_KEY` value in your `.env` file to
|
||||
your [OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-api-key).
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Run your GenAI application
|
||||
|
||||
At this point, you have the following services in your Compose file:
|
||||
|
||||
- Server service for your main GenAI application
|
||||
- Database service to store vectors in a Neo4j database
|
||||
- (optional) Ollama service to run the LLM
|
||||
- (optional) Ollama-pull service to automatically pull the model for the Ollama
|
||||
service
|
||||
|
||||
To run all the services, run the following command in your `docker-genai-sample`
|
||||
directory:
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
If your Compose file has the ollama-pull service, it may take several minutes for the ollama-pull service to pull the model. The ollama-pull service will continuously update the console with its status. After pulling the model, the ollama-pull service container will stop and you can access the application.
|
||||
|
||||
Once the application is running, open a browser and access the application at [http://localhost:8000](http://localhost:8000).
|
||||
|
||||
Upload a PDF file, for example the [Docker CLI Cheat Sheet](https://docs.docker.com/get-started/docker_cheatsheet.pdf), and ask a question about the PDF.
|
||||
|
||||
Depending on your system and the LLM service that you chose, it may take several
|
||||
minutes to answer. If you are using Ollama and the performance isn't
|
||||
acceptable, try using OpenAI.
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you learned how to set up a development environment to provide
|
||||
access all the services that your GenAI application needs.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Dockerfile reference](../../../reference/dockerfile.md)
|
||||
- [Compose file reference](/reference/compose-file/_index.md)
|
||||
- [Ollama Docker image](https://hub.docker.com/r/ollama/ollama)
|
||||
- [Neo4j Official Docker Image](https://hub.docker.com/_/neo4j)
|
||||
- [GenAI Stack demo applications](https://github.com/docker/genai-stack)
|
||||
|
||||
### Next steps
|
||||
|
||||
See samples of more GenAI applications in the [GenAI Stack demo applications](https://github.com/docker/genai-stack).
|
||||
@@ -6,10 +6,10 @@ keywords: python, generative ai, genai, llm, whisper, pinecone, openai, whisper
|
||||
summary: |
|
||||
Learn how to build and deploy a generative AI video analysis and
|
||||
transcription bot using Docker.
|
||||
tags: [ai]
|
||||
aliases:
|
||||
- /guides/use-case/genai-video-bot/
|
||||
params:
|
||||
tags: [ai]
|
||||
time: 20 minutes
|
||||
---
|
||||
|
||||
@@ -78,14 +78,14 @@ addition, it provides timestamps from the video that can help you find the sourc
|
||||
called `.env` and specify your API keys inside. The following is the contents of the `.env.example` file that you can refer to as an example.
|
||||
|
||||
```text
|
||||
#----------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
# OpenAI
|
||||
#----------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
OPENAI_TOKEN=your-api-key # Replace your-api-key with your personal API key
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
# Pinecone
|
||||
#----------------------------------------------------------------------------
|
||||
#-------------------------------------------------------------------------
|
||||
PINECONE_TOKEN=your-api-key # Replace your-api-key with your personal API key
|
||||
```
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ summary: |
|
||||
Learn how to automate image build and push with GitHub Actions.
|
||||
keywords: github actions, ci/cd, docker hub, build and push, automation, workflows
|
||||
params:
|
||||
tags: [devops]
|
||||
tags: [cicd]
|
||||
time: 10 minutes
|
||||
---
|
||||
|
||||
@@ -252,5 +252,6 @@ additional features based on your project's needs, such as
|
||||
### Further reading
|
||||
|
||||
- Learn more about advanced configurations and examples in the [Docker Build GitHub Actions](/manuals/build/ci/github-actions/_index.md) section.
|
||||
- For more complex build setups, you may want to consider [Bake](/manuals/build/bake/_index.md). (See also the [Mastering Buildx Bake guide](/guides/bake/index.md).)
|
||||
- For more complex build setups, you may want to consider [Bake](/manuals/build/bake/_index.md). (See also the [Mastering Buildx Bake guide](/guides/bake/).)
|
||||
|
||||
- Learn about Docker's managed build service, designed for faster, multi-platform builds, see [Docker Build Cloud](/guides/docker-build-cloud/_index.md).
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
title: How to build an AI-powered code quality workflow with SonarQube and E2B
|
||||
linkTitle: AI-powered code quality
|
||||
summary: Build AI-powered code quality workflows using E2B sandboxes with Docker's MCP catalog to automate GitHub and SonarQube integration.
|
||||
description: Learn how to create E2B sandboxes with MCP servers, analyze code quality with SonarQube, and generate quality-gated pull requests using GitHub—all through natural language interactions with Claude.
|
||||
keywords: sonarqube, e2b, sandboxes, mcp, github, code quality, ai workflow, claude
|
||||
tags: [devops]
|
||||
params:
|
||||
time: 40 minutes
|
||||
image:
|
||||
resource_links:
|
||||
- title: E2B Documentation
|
||||
url: https://e2b.dev/docs
|
||||
- title: Docker MCP Catalog
|
||||
url: https://hub.docker.com/mcp
|
||||
- title: Sandboxes
|
||||
url: https://docs.docker.com/ai/mcp-catalog-and-toolkit/sandboxes/
|
||||
---
|
||||
|
||||
This guide demonstrates how to build an AI-powered code quality workflow using
|
||||
[E2B sandboxes](https://e2b.dev/docs) with Docker’s MCP catalog. You’ll create
|
||||
a system that automatically analyzes code quality issues in GitHub repositories
|
||||
using SonarQube, then generate pull requests with fixes.
|
||||
|
||||
## What you'll build
|
||||
|
||||
You’ll build a Node.js script that spins up an E2B sandbox, connects GitHub and
|
||||
SonarQube MCP servers, and uses Claude Code to analyze code quality and propose
|
||||
improvements. The MCP servers are containerized and run as part of the E2B
|
||||
sandbox.
|
||||
|
||||
## What you'll learn
|
||||
|
||||
In this guide, you'll learn:
|
||||
|
||||
- How to create E2B sandboxes with multiple MCP servers
|
||||
- How to configure GitHub and SonarQube MCP servers for AI workflows
|
||||
- How to use Claude Code inside sandboxes to interact with external tools
|
||||
- How to build automated code review workflows that create quality-gated
|
||||
pull requests
|
||||
|
||||
## Why use E2B sandboxes?
|
||||
|
||||
Running this workflow in E2B sandboes provides several advantages over
|
||||
local execution:
|
||||
|
||||
- Security: AI-generated code runs in isolated containers, protecting your
|
||||
local environment and credentials
|
||||
- Zero setup: No need to install SonarQube, GitHub CLI, or manage dependencies
|
||||
locally
|
||||
- Scalability: Resource-intensive operations like code scanning run in the
|
||||
cloud without consuming local resources
|
||||
|
||||
## Learn more
|
||||
|
||||
Read Docker's blog post: [Docker + E2B: Building the Future of Trusted AI](https://www.docker.com/blog/docker-e2b-building-the-future-of-trusted-ai/).
|
||||
@@ -1,182 +0,0 @@
|
||||
---
|
||||
title: Customize a code quality check workflow
|
||||
linkTitle: Customize workflow
|
||||
summary: Adapt your GitHub and SonarQube workflow to focus on specific quality issues, integrate with CI/CD, and set custom thresholds.
|
||||
description: Learn how to customize prompts for specific quality issues, filter by file patterns, set quality thresholds, and integrate your workflow with GitHub Actions for automated code quality checks.
|
||||
keywords: sonarqube, e2b, mcp, github actions, code quality, customization, ci/cd
|
||||
weight: 20
|
||||
---
|
||||
|
||||
Now that you understand the basics of automating code quality workflows with
|
||||
GitHub and SonarQube in E2B sandboxes, you can customize the workflow
|
||||
for your needs.
|
||||
|
||||
## Focus on specific quality issues
|
||||
|
||||
Modify the prompt to prioritize certain issue types:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
const prompt = `Using SonarQube and GitHub MCP tools:
|
||||
|
||||
Focus only on:
|
||||
- Security vulnerabilities (CRITICAL priority)
|
||||
- Bugs (HIGH priority)
|
||||
- Skip code smells for this iteration
|
||||
|
||||
Analyze "${repoPath}" and fix the highest priority issues first.`;
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
prompt = f"""Using SonarQube and GitHub MCP tools:
|
||||
|
||||
Focus only on:
|
||||
- Security vulnerabilities (CRITICAL priority)
|
||||
- Bugs (HIGH priority)
|
||||
- Skip code smells for this iteration
|
||||
|
||||
Analyze "{repo_path}" and fix the highest priority issues first."""
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Integrate with CI/CD
|
||||
|
||||
Add this workflow to GitHub Actions to run automatically on pull requests:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```yaml
|
||||
name: Automated quality checks
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@{{% param "checkout_action_version" %}}
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: "24"
|
||||
- run: npm install
|
||||
- run: npx tsx 06-quality-gated-pr.ts
|
||||
env:
|
||||
E2B_API_KEY: ${{ secrets.E2B_API_KEY }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
GITHUB_OWNER: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
SONARQUBE_ORG: your-org-key
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```yaml
|
||||
name: Automated quality checks
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@{{% param "checkout_action_version" %}}
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
- run: pip install e2b python-dotenv
|
||||
- run: python 06_quality_gated_pr.py
|
||||
env:
|
||||
E2B_API_KEY: ${{ secrets.E2B_API_KEY }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
GITHUB_OWNER: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
SONARQUBE_ORG: your-org-key
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Filter by file patterns
|
||||
|
||||
Target specific parts of your codebase:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
const prompt = `Analyze code quality but only consider:
|
||||
- Files in src/**/*.js
|
||||
- Exclude test files (*.test.js, *.spec.js)
|
||||
- Exclude build artifacts in dist/
|
||||
|
||||
Focus on production code only.`;
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
prompt = """Analyze code quality but only consider:
|
||||
- Files in src/**/*.js
|
||||
- Exclude test files (*.test.js, *.spec.js)
|
||||
- Exclude build artifacts in dist/
|
||||
|
||||
Focus on production code only."""
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Set quality thresholds
|
||||
|
||||
Define when PRs should be created:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
const prompt = `Quality gate thresholds:
|
||||
- Only create PR if:
|
||||
* Bug count decreases by at least 1
|
||||
* No new security vulnerabilities introduced
|
||||
* Code coverage does not decrease
|
||||
* Technical debt reduces by at least 15 minutes
|
||||
|
||||
If changes do not meet these thresholds, explain why and skip PR creation.`;
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
prompt = """Quality gate thresholds:
|
||||
- Only create PR if:
|
||||
* Bug count decreases by at least 1
|
||||
* No new security vulnerabilities introduced
|
||||
* Code coverage does not decrease
|
||||
* Technical debt reduces by at least 15 minutes
|
||||
|
||||
If changes do not meet these thresholds, explain why and skip PR creation."""
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Next steps
|
||||
|
||||
Learn how to troubleshoot common issues.
|
||||
@@ -1,12 +1,60 @@
|
||||
---
|
||||
title: Build a code quality check workflow
|
||||
linkTitle: Build workflow
|
||||
summary: Learn to use GitHub and SonarQube MCP servers in E2B sandboxes through progressive examples.
|
||||
description: Create E2B sandboxes, discover MCP tools, test individual operations, and build complete quality-gated PR workflows.
|
||||
keywords: sonarqube, e2b, mcp, github, code quality, pull requests, workflow
|
||||
weight: 10
|
||||
title: How to build an AI-powered code quality workflow with SonarQube and E2B
|
||||
linkTitle: AI-powered code quality
|
||||
summary: Build AI-powered code quality workflows using E2B sandboxes with Docker's MCP catalog to automate GitHub and SonarQube integration.
|
||||
description: Learn how to create E2B sandboxes with MCP servers, analyze code quality with SonarQube, and generate quality-gated pull requests using GitHub—all through natural language interactions with Claude.
|
||||
keywords: sonarqube, e2b, sandboxes, mcp, github, code quality, ai workflow, claude
|
||||
aliases:
|
||||
- /guides/github-sonarqube-sandbox/customize/
|
||||
- /guides/github-sonarqube-sandbox/troubleshoot/
|
||||
- /guides/github-sonarqube-sandbox/workflow/
|
||||
params:
|
||||
tags: [cicd]
|
||||
time: 40 minutes
|
||||
image:
|
||||
---
|
||||
|
||||
|
||||
This guide demonstrates how to build an AI-powered code quality workflow using
|
||||
[E2B sandboxes](https://e2b.dev/docs) with Docker’s MCP catalog. You’ll create
|
||||
a system that automatically analyzes code quality issues in GitHub repositories
|
||||
using SonarQube, then generate pull requests with fixes.
|
||||
|
||||
## What you'll build
|
||||
|
||||
You’ll build a Node.js script that spins up an E2B sandbox, connects GitHub and
|
||||
SonarQube MCP servers, and uses Claude Code to analyze code quality and propose
|
||||
improvements. The MCP servers are containerized and run as part of the E2B
|
||||
sandbox.
|
||||
|
||||
## What you'll learn
|
||||
|
||||
In this guide, you'll learn:
|
||||
|
||||
- How to create E2B sandboxes with multiple MCP servers
|
||||
- How to configure GitHub and SonarQube MCP servers for AI workflows
|
||||
- How to use Claude Code inside sandboxes to interact with external tools
|
||||
- How to build automated code review workflows that create quality-gated
|
||||
pull requests
|
||||
|
||||
## Why use E2B sandboxes?
|
||||
|
||||
Running this workflow in E2B sandboes provides several advantages over
|
||||
local execution:
|
||||
|
||||
- Security: AI-generated code runs in isolated containers, protecting your
|
||||
local environment and credentials
|
||||
- Zero setup: No need to install SonarQube, GitHub CLI, or manage dependencies
|
||||
locally
|
||||
- Scalability: Resource-intensive operations like code scanning run in the
|
||||
cloud without consuming local resources
|
||||
|
||||
## Learn more
|
||||
|
||||
Read Docker's blog post: [Docker + E2B: Building the Future of Trusted AI](https://www.docker.com/blog/docker-e2b-building-the-future-of-trusted-ai/).
|
||||
|
||||
## Build a code quality check workflow
|
||||
|
||||
In this section, you'll build a complete code quality automation workflow
|
||||
step-by-step. You'll start by creating an E2B sandbox with GitHub and
|
||||
SonarQube MCP servers, then progressively add functionality until you have a
|
||||
@@ -16,7 +64,7 @@ By working through each step sequentially, you'll learn how MCP servers work,
|
||||
how to interact with them through Claude, and how to chain operations together
|
||||
to build powerful automation workflows.
|
||||
|
||||
## Prerequisites
|
||||
### Prerequisites
|
||||
|
||||
Before you begin, make sure you have:
|
||||
|
||||
@@ -50,7 +98,7 @@ Before you begin, make sure you have:
|
||||
> use this approach with trusted code and workflows. For more information,
|
||||
> see [Anthropic's guidance on container security](https://docs.anthropic.com/en/docs/claude-code/devcontainer).
|
||||
|
||||
## Set up your project
|
||||
### Set up your project
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
@@ -167,7 +215,7 @@ Before you begin, make sure you have:
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Step 1: Create your first sandbox
|
||||
### Step 1: Create your first sandbox
|
||||
|
||||
Let's start by creating a sandbox and verifying the MCP servers are configured correctly.
|
||||
|
||||
@@ -326,7 +374,7 @@ You've just learned how to create an E2B sandbox with multiple MCP servers
|
||||
configured. The `betaCreate` method initializes a cloud environment
|
||||
with Claude CLI and your specified MCP servers.
|
||||
|
||||
## Step 2: Discover available MCP tools
|
||||
### Step 2: Discover available MCP tools
|
||||
|
||||
MCP servers expose tools that Claude can call. The GitHub MCP server provides
|
||||
repository management tools, while SonarQube provides code analysis tools.
|
||||
@@ -501,7 +549,7 @@ I have access to the following MCP tools:
|
||||
... (SonarQube analysis tools)
|
||||
```
|
||||
|
||||
## Step 3: Test GitHub MCP tools
|
||||
### Step 3: Test GitHub MCP tools
|
||||
|
||||
Let's try testing GitHub using MCP tools. Start simple by listing
|
||||
repository issues.
|
||||
@@ -656,7 +704,7 @@ Here are the first 10 open issues in the <your-repo> repository:
|
||||
You can now send prompts to Claude and interact with GitHub through
|
||||
natural language. Claude decides what tool to call based on your prompt.
|
||||
|
||||
## Step 4: Test SonarQube MCP tools
|
||||
### Step 4: Test SonarQube MCP tools
|
||||
|
||||
Let's analyze code quality using SonarQube MCP tools.
|
||||
|
||||
@@ -850,7 +898,7 @@ You can now use SonarQube MCP tools to analyze code quality through
|
||||
natural language. You can retrieve quality metrics, identify issues,
|
||||
and understand what code needs fixing.
|
||||
|
||||
## Step 5: Create a branch and make code changes
|
||||
### Step 5: Create a branch and make code changes
|
||||
|
||||
Now, let's teach Claude to fix code based on quality issues discovered
|
||||
by SonarQube.
|
||||
@@ -1068,7 +1116,7 @@ The fix is ready for review and can be merged to improve the code quality of the
|
||||
You can now use GitHub and SonarQube MCP tools in the same workflow to read
|
||||
files, make code changes, and commit them.
|
||||
|
||||
## Step 6: Create quality-gated pull requests
|
||||
### Step 6: Create quality-gated pull requests
|
||||
|
||||
Finally, let's build the complete workflow: analyze quality, fix issues,
|
||||
and create a PR only if improvements are made.
|
||||
@@ -1373,7 +1421,7 @@ You've now built a complete, multi-step workflow with conditional logic.
|
||||
Claude analyzes quality with SonarQube, makes fixes using GitHub tools,
|
||||
verifies improvements, and only creates a PR if quality actually improves.
|
||||
|
||||
## Step 7: Add error handling
|
||||
### Step 7: Add error handling
|
||||
|
||||
Production workflows need error handling. Let's make the workflow more robust.
|
||||
|
||||
@@ -1583,6 +1631,510 @@ python 07_robust_workflow.py
|
||||
Claude will run the entire workflow, and if it encounters an error, respond
|
||||
with robust error messaging.
|
||||
|
||||
## Next steps
|
||||
### Next steps
|
||||
|
||||
In the next section, you'll customize your workflow for your needs.
|
||||
|
||||
## Customize a code quality check workflow
|
||||
|
||||
Now that you understand the basics of automating code quality workflows with
|
||||
GitHub and SonarQube in E2B sandboxes, you can customize the workflow
|
||||
for your needs.
|
||||
|
||||
### Focus on specific quality issues
|
||||
|
||||
Modify the prompt to prioritize certain issue types:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
const prompt = `Using SonarQube and GitHub MCP tools:
|
||||
|
||||
Focus only on:
|
||||
- Security vulnerabilities (CRITICAL priority)
|
||||
- Bugs (HIGH priority)
|
||||
- Skip code smells for this iteration
|
||||
|
||||
Analyze "${repoPath}" and fix the highest priority issues first.`;
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
prompt = f"""Using SonarQube and GitHub MCP tools:
|
||||
|
||||
Focus only on:
|
||||
- Security vulnerabilities (CRITICAL priority)
|
||||
- Bugs (HIGH priority)
|
||||
- Skip code smells for this iteration
|
||||
|
||||
Analyze "{repo_path}" and fix the highest priority issues first."""
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Integrate with CI/CD
|
||||
|
||||
Add this workflow to GitHub Actions to run automatically on pull requests:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```yaml
|
||||
name: Automated quality checks
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@{{% param "checkout_action_version" %}}
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: "24"
|
||||
- run: npm install
|
||||
- run: npx tsx 06-quality-gated-pr.ts
|
||||
env:
|
||||
E2B_API_KEY: ${{ secrets.E2B_API_KEY }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
GITHUB_OWNER: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
SONARQUBE_ORG: your-org-key
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```yaml
|
||||
name: Automated quality checks
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
quality:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@{{% param "checkout_action_version" %}}
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
- run: pip install e2b python-dotenv
|
||||
- run: python 06_quality_gated_pr.py
|
||||
env:
|
||||
E2B_API_KEY: ${{ secrets.E2B_API_KEY }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONARQUBE_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
GITHUB_OWNER: ${{ github.repository_owner }}
|
||||
GITHUB_REPO: ${{ github.event.repository.name }}
|
||||
SONARQUBE_ORG: your-org-key
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Filter by file patterns
|
||||
|
||||
Target specific parts of your codebase:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
const prompt = `Analyze code quality but only consider:
|
||||
- Files in src/**/*.js
|
||||
- Exclude test files (*.test.js, *.spec.js)
|
||||
- Exclude build artifacts in dist/
|
||||
|
||||
Focus on production code only.`;
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
prompt = """Analyze code quality but only consider:
|
||||
- Files in src/**/*.js
|
||||
- Exclude test files (*.test.js, *.spec.js)
|
||||
- Exclude build artifacts in dist/
|
||||
|
||||
Focus on production code only."""
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Set quality thresholds
|
||||
|
||||
Define when PRs should be created:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
const prompt = `Quality gate thresholds:
|
||||
- Only create PR if:
|
||||
* Bug count decreases by at least 1
|
||||
* No new security vulnerabilities introduced
|
||||
* Code coverage does not decrease
|
||||
* Technical debt reduces by at least 15 minutes
|
||||
|
||||
If changes do not meet these thresholds, explain why and skip PR creation.`;
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
prompt = """Quality gate thresholds:
|
||||
- Only create PR if:
|
||||
* Bug count decreases by at least 1
|
||||
* No new security vulnerabilities introduced
|
||||
* Code coverage does not decrease
|
||||
* Technical debt reduces by at least 15 minutes
|
||||
|
||||
If changes do not meet these thresholds, explain why and skip PR creation."""
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Next steps
|
||||
|
||||
Learn how to troubleshoot common issues.
|
||||
|
||||
## Troubleshoot code quality workflows
|
||||
|
||||
This page covers common issues you might encounter when building code quality
|
||||
workflows with E2B sandboxes and MCP servers, along with their solutions.
|
||||
|
||||
If you're experiencing problems not covered here, check the
|
||||
[E2B documentation](https://e2b.dev/docs).
|
||||
|
||||
### MCP tools not available
|
||||
|
||||
Issue: Claude reports `I don't have any MCP tools available`.
|
||||
|
||||
Solution:
|
||||
|
||||
1. Verify you're using the authorization header:
|
||||
|
||||
```plaintext
|
||||
--header "Authorization: Bearer ${mcpToken}"
|
||||
```
|
||||
|
||||
2. Check you're waiting for MCP initialization.
|
||||
|
||||
```typescript
|
||||
// typescript
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
await asyncio.sleep(1)
|
||||
```
|
||||
|
||||
3. Ensure credentials are in both `envs` and `mcp` configuration:
|
||||
|
||||
```typescript
|
||||
// typescript
|
||||
const sbx = await Sandbox.betaCreate({
|
||||
envs: {
|
||||
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,
|
||||
GITHUB_TOKEN: process.env.GITHUB_TOKEN!,
|
||||
SONARQUBE_TOKEN: process.env.SONARQUBE_TOKEN!,
|
||||
},
|
||||
mcp: {
|
||||
githubOfficial: {
|
||||
githubPersonalAccessToken: process.env.GITHUB_TOKEN!,
|
||||
},
|
||||
sonarqube: {
|
||||
org: process.env.SONARQUBE_ORG!,
|
||||
token: process.env.SONARQUBE_TOKEN!,
|
||||
url: "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
sbx = await AsyncSandbox.beta_create(
|
||||
envs={
|
||||
"ANTHROPIC_API_KEY": os.getenv("ANTHROPIC_API_KEY"),
|
||||
"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN"),
|
||||
"SONARQUBE_TOKEN": os.getenv("SONARQUBE_TOKEN"),
|
||||
},
|
||||
mcp={
|
||||
"githubOfficial": {
|
||||
"githubPersonalAccessToken": os.getenv("GITHUB_TOKEN"),
|
||||
},
|
||||
"sonarqube": {
|
||||
"org": os.getenv("SONARQUBE_ORG"),
|
||||
"token": os.getenv("SONARQUBE_TOKEN"),
|
||||
"url": "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
4. Verify your API tokens are valid and have proper scopes.
|
||||
|
||||
### GitHub tools work but SonarQube doesn't
|
||||
|
||||
Issue: GitHub MCP tools load but SonarQube tools don't appear.
|
||||
|
||||
Solution: SonarQube MCP server requires GitHub to be configured simultaneously.
|
||||
Always include both servers in your sandbox configuration, even if you're only
|
||||
testing one.
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
// Include both servers even if only using one
|
||||
const sbx = await Sandbox.betaCreate({
|
||||
envs: {
|
||||
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,
|
||||
GITHUB_TOKEN: process.env.GITHUB_TOKEN!,
|
||||
SONARQUBE_TOKEN: process.env.SONARQUBE_TOKEN!,
|
||||
},
|
||||
mcp: {
|
||||
githubOfficial: {
|
||||
githubPersonalAccessToken: process.env.GITHUB_TOKEN!,
|
||||
},
|
||||
sonarqube: {
|
||||
org: process.env.SONARQUBE_ORG!,
|
||||
token: process.env.SONARQUBE_TOKEN!,
|
||||
url: "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
# Include both servers even if only using one
|
||||
sbx = await AsyncSandbox.beta_create(
|
||||
envs={
|
||||
"ANTHROPIC_API_KEY": os.getenv("ANTHROPIC_API_KEY"),
|
||||
"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN"),
|
||||
"SONARQUBE_TOKEN": os.getenv("SONARQUBE_TOKEN"),
|
||||
},
|
||||
mcp={
|
||||
"githubOfficial": {
|
||||
"githubPersonalAccessToken": os.getenv("GITHUB_TOKEN"),
|
||||
},
|
||||
"sonarqube": {
|
||||
"org": os.getenv("SONARQUBE_ORG"),
|
||||
"token": os.getenv("SONARQUBE_TOKEN"),
|
||||
"url": "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Claude can't access private repositories
|
||||
|
||||
Issue: "I don't have access to that repository".
|
||||
|
||||
Solution:
|
||||
|
||||
1. Verify your GitHub token has `repo` scope (not just `public_repo`).
|
||||
2. Test with a public repository first.
|
||||
3. Ensure the repository owner and name are correct in your `.env`:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```plaintext
|
||||
GITHUB_OWNER=your_github_username
|
||||
GITHUB_REPO=your_repository_name
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```plaintext
|
||||
GITHUB_OWNER=your_github_username
|
||||
GITHUB_REPO=your_repository_name
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Workflow times out or runs too long
|
||||
|
||||
Issue: Workflow doesn't complete or Claude credits run out.
|
||||
|
||||
Solutions:
|
||||
|
||||
1. Use `timeoutMs: 0` (TypeScript) or `timeout_ms=0` (Python) for complex workflows to allow unlimited time:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
await sbx.commands.run(
|
||||
`echo '${prompt}' | claude -p --dangerously-skip-permissions`,
|
||||
{
|
||||
timeoutMs: 0, // No timeout
|
||||
onStdout: console.log,
|
||||
onStderr: console.log,
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
await sbx.commands.run(
|
||||
f"echo '{prompt}' | claude -p --dangerously-skip-permissions",
|
||||
timeout_ms=0, # No timeout
|
||||
on_stdout=print,
|
||||
on_stderr=print,
|
||||
)
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
2. Break complex workflows into smaller, focused tasks.
|
||||
3. Monitor your Anthropic API credit usage.
|
||||
4. Add checkpoints in prompts: "After each step, show progress before continuing".
|
||||
|
||||
### Sandbox cleanup errors
|
||||
|
||||
Issue: Sandboxes aren't being cleaned up properly, leading to resource exhaustion.
|
||||
|
||||
Solution: Always use proper error handling with cleanup in the `finally` block:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
async function robustWorkflow() {
|
||||
let sbx: Sandbox | undefined;
|
||||
|
||||
try {
|
||||
sbx = await Sandbox.betaCreate({
|
||||
// ... configuration
|
||||
});
|
||||
|
||||
// ... workflow logic
|
||||
} catch (error) {
|
||||
console.error("Workflow failed:", error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
if (sbx) {
|
||||
console.log("Cleaning up sandbox...");
|
||||
await sbx.kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
async def robust_workflow():
|
||||
sbx = None
|
||||
|
||||
try:
|
||||
sbx = await AsyncSandbox.beta_create(
|
||||
# ... configuration
|
||||
)
|
||||
|
||||
# ... workflow logic
|
||||
|
||||
except Exception as error:
|
||||
print(f"Workflow failed: {error}")
|
||||
sys.exit(1)
|
||||
finally:
|
||||
if sbx:
|
||||
print("Cleaning up sandbox...")
|
||||
await sbx.kill()
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### Environment variable not loading
|
||||
|
||||
Issue: Script fails with "undefined" or "None" for environment variables.
|
||||
|
||||
Solution:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
1. Ensure `dotenv` is loaded at the top of your file:
|
||||
|
||||
```typescript
|
||||
import "dotenv/config";
|
||||
```
|
||||
|
||||
2. Verify the `.env` file is in the same directory as your script.
|
||||
|
||||
3. Check variable names match exactly (case-sensitive):
|
||||
|
||||
```typescript
|
||||
// .env file
|
||||
GITHUB_TOKEN = ghp_xxxxx;
|
||||
|
||||
// In code
|
||||
process.env.GITHUB_TOKEN; // Correct
|
||||
process.env.github_token; // Wrong - case doesn't match
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
1. Ensure `dotenv` is loaded at the top of your file:
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
```
|
||||
|
||||
2. Verify the `.env` file is in the same directory as your script.
|
||||
|
||||
3. Check variable names match exactly (case-sensitive):
|
||||
|
||||
```python
|
||||
# .env file
|
||||
GITHUB_TOKEN=ghp_xxxxx
|
||||
|
||||
# In code
|
||||
os.getenv("GITHUB_TOKEN") # Correct
|
||||
os.getenv("github_token") # Wrong - case doesn't match
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
### SonarQube returns empty results
|
||||
|
||||
Issue: SonarQube analysis returns no projects or issues.
|
||||
|
||||
Solution:
|
||||
|
||||
1. Verify your SonarCloud organization key is correct.
|
||||
2. Ensure you have at least one project configured in SonarCloud.
|
||||
3. Check that your SonarQube token has the necessary permissions.
|
||||
4. Confirm your project has been analyzed at least once in SonarCloud.
|
||||
@@ -1,334 +0,0 @@
|
||||
---
|
||||
title: Troubleshoot code quality workflows
|
||||
linkTitle: Troubleshoot
|
||||
summary: Resolve common issues with E2B sandboxes, MCP server connections, and GitHub/SonarQube integration.
|
||||
description: Solutions for MCP tools not loading, authentication errors, permission issues, workflow timeouts, and other common problems when building code quality workflows with E2B.
|
||||
keywords: sonarqube, e2b, mcp, troubleshooting, debugging, authentication, code quality
|
||||
weight: 30
|
||||
---
|
||||
|
||||
This page covers common issues you might encounter when building code quality
|
||||
workflows with E2B sandboxes and MCP servers, along with their solutions.
|
||||
|
||||
If you're experiencing problems not covered here, check the
|
||||
[E2B documentation](https://e2b.dev/docs).
|
||||
|
||||
## MCP tools not available
|
||||
|
||||
Issue: Claude reports `I don't have any MCP tools available`.
|
||||
|
||||
Solution:
|
||||
|
||||
1. Verify you're using the authorization header:
|
||||
|
||||
```plaintext
|
||||
--header "Authorization: Bearer ${mcpToken}"
|
||||
```
|
||||
|
||||
2. Check you're waiting for MCP initialization.
|
||||
|
||||
```typescript
|
||||
// typescript
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
await asyncio.sleep(1)
|
||||
```
|
||||
|
||||
3. Ensure credentials are in both `envs` and `mcp` configuration:
|
||||
|
||||
```typescript
|
||||
// typescript
|
||||
const sbx = await Sandbox.betaCreate({
|
||||
envs: {
|
||||
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,
|
||||
GITHUB_TOKEN: process.env.GITHUB_TOKEN!,
|
||||
SONARQUBE_TOKEN: process.env.SONARQUBE_TOKEN!,
|
||||
},
|
||||
mcp: {
|
||||
githubOfficial: {
|
||||
githubPersonalAccessToken: process.env.GITHUB_TOKEN!,
|
||||
},
|
||||
sonarqube: {
|
||||
org: process.env.SONARQUBE_ORG!,
|
||||
token: process.env.SONARQUBE_TOKEN!,
|
||||
url: "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```python
|
||||
# python
|
||||
sbx = await AsyncSandbox.beta_create(
|
||||
envs={
|
||||
"ANTHROPIC_API_KEY": os.getenv("ANTHROPIC_API_KEY"),
|
||||
"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN"),
|
||||
"SONARQUBE_TOKEN": os.getenv("SONARQUBE_TOKEN"),
|
||||
},
|
||||
mcp={
|
||||
"githubOfficial": {
|
||||
"githubPersonalAccessToken": os.getenv("GITHUB_TOKEN"),
|
||||
},
|
||||
"sonarqube": {
|
||||
"org": os.getenv("SONARQUBE_ORG"),
|
||||
"token": os.getenv("SONARQUBE_TOKEN"),
|
||||
"url": "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
4. Verify your API tokens are valid and have proper scopes.
|
||||
|
||||
## GitHub tools work but SonarQube doesn't
|
||||
|
||||
Issue: GitHub MCP tools load but SonarQube tools don't appear.
|
||||
|
||||
Solution: SonarQube MCP server requires GitHub to be configured simultaneously.
|
||||
Always include both servers in your sandbox configuration, even if you're only
|
||||
testing one.
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
// Include both servers even if only using one
|
||||
const sbx = await Sandbox.betaCreate({
|
||||
envs: {
|
||||
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,
|
||||
GITHUB_TOKEN: process.env.GITHUB_TOKEN!,
|
||||
SONARQUBE_TOKEN: process.env.SONARQUBE_TOKEN!,
|
||||
},
|
||||
mcp: {
|
||||
githubOfficial: {
|
||||
githubPersonalAccessToken: process.env.GITHUB_TOKEN!,
|
||||
},
|
||||
sonarqube: {
|
||||
org: process.env.SONARQUBE_ORG!,
|
||||
token: process.env.SONARQUBE_TOKEN!,
|
||||
url: "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
# Include both servers even if only using one
|
||||
sbx = await AsyncSandbox.beta_create(
|
||||
envs={
|
||||
"ANTHROPIC_API_KEY": os.getenv("ANTHROPIC_API_KEY"),
|
||||
"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN"),
|
||||
"SONARQUBE_TOKEN": os.getenv("SONARQUBE_TOKEN"),
|
||||
},
|
||||
mcp={
|
||||
"githubOfficial": {
|
||||
"githubPersonalAccessToken": os.getenv("GITHUB_TOKEN"),
|
||||
},
|
||||
"sonarqube": {
|
||||
"org": os.getenv("SONARQUBE_ORG"),
|
||||
"token": os.getenv("SONARQUBE_TOKEN"),
|
||||
"url": "https://sonarcloud.io",
|
||||
},
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Claude can't access private repositories
|
||||
|
||||
Issue: "I don't have access to that repository".
|
||||
|
||||
Solution:
|
||||
|
||||
1. Verify your GitHub token has `repo` scope (not just `public_repo`).
|
||||
2. Test with a public repository first.
|
||||
3. Ensure the repository owner and name are correct in your `.env`:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```plaintext
|
||||
GITHUB_OWNER=your_github_username
|
||||
GITHUB_REPO=your_repository_name
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```plaintext
|
||||
GITHUB_OWNER=your_github_username
|
||||
GITHUB_REPO=your_repository_name
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Workflow times out or runs too long
|
||||
|
||||
Issue: Workflow doesn't complete or Claude credits run out.
|
||||
|
||||
Solutions:
|
||||
|
||||
1. Use `timeoutMs: 0` (TypeScript) or `timeout_ms=0` (Python) for complex workflows to allow unlimited time:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
await sbx.commands.run(
|
||||
`echo '${prompt}' | claude -p --dangerously-skip-permissions`,
|
||||
{
|
||||
timeoutMs: 0, // No timeout
|
||||
onStdout: console.log,
|
||||
onStderr: console.log,
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
await sbx.commands.run(
|
||||
f"echo '{prompt}' | claude -p --dangerously-skip-permissions",
|
||||
timeout_ms=0, # No timeout
|
||||
on_stdout=print,
|
||||
on_stderr=print,
|
||||
)
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
2. Break complex workflows into smaller, focused tasks.
|
||||
3. Monitor your Anthropic API credit usage.
|
||||
4. Add checkpoints in prompts: "After each step, show progress before continuing".
|
||||
|
||||
## Sandbox cleanup errors
|
||||
|
||||
Issue: Sandboxes aren't being cleaned up properly, leading to resource exhaustion.
|
||||
|
||||
Solution: Always use proper error handling with cleanup in the `finally` block:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
```typescript
|
||||
async function robustWorkflow() {
|
||||
let sbx: Sandbox | undefined;
|
||||
|
||||
try {
|
||||
sbx = await Sandbox.betaCreate({
|
||||
// ... configuration
|
||||
});
|
||||
|
||||
// ... workflow logic
|
||||
} catch (error) {
|
||||
console.error("Workflow failed:", error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
if (sbx) {
|
||||
console.log("Cleaning up sandbox...");
|
||||
await sbx.kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
|
||||
```python
|
||||
async def robust_workflow():
|
||||
sbx = None
|
||||
|
||||
try:
|
||||
sbx = await AsyncSandbox.beta_create(
|
||||
# ... configuration
|
||||
)
|
||||
|
||||
# ... workflow logic
|
||||
|
||||
except Exception as error:
|
||||
print(f"Workflow failed: {error}")
|
||||
sys.exit(1)
|
||||
finally:
|
||||
if sbx:
|
||||
print("Cleaning up sandbox...")
|
||||
await sbx.kill()
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Environment variable not loading
|
||||
|
||||
Issue: Script fails with "undefined" or "None" for environment variables.
|
||||
|
||||
Solution:
|
||||
|
||||
{{< tabs group="language" >}}
|
||||
{{< tab name="TypeScript" >}}
|
||||
|
||||
1. Ensure `dotenv` is loaded at the top of your file:
|
||||
|
||||
```typescript
|
||||
import "dotenv/config";
|
||||
```
|
||||
|
||||
2. Verify the `.env` file is in the same directory as your script.
|
||||
|
||||
3. Check variable names match exactly (case-sensitive):
|
||||
|
||||
```typescript
|
||||
// .env file
|
||||
GITHUB_TOKEN = ghp_xxxxx;
|
||||
|
||||
// In code
|
||||
process.env.GITHUB_TOKEN; // Correct
|
||||
process.env.github_token; // Wrong - case doesn't match
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< tab name="Python" >}}
|
||||
1. Ensure `dotenv` is loaded at the top of your file:
|
||||
|
||||
```python
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
```
|
||||
|
||||
2. Verify the `.env` file is in the same directory as your script.
|
||||
|
||||
3. Check variable names match exactly (case-sensitive):
|
||||
|
||||
```python
|
||||
# .env file
|
||||
GITHUB_TOKEN=ghp_xxxxx
|
||||
|
||||
# In code
|
||||
os.getenv("GITHUB_TOKEN") # Correct
|
||||
os.getenv("github_token") # Wrong - case doesn't match
|
||||
```
|
||||
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## SonarQube returns empty results
|
||||
|
||||
Issue: SonarQube analysis returns no projects or issues.
|
||||
|
||||
Solution:
|
||||
|
||||
1. Verify your SonarCloud organization key is correct.
|
||||
2. Ensure you have at least one project configured in SonarCloud.
|
||||
3. Check that your SonarQube token has the necessary permissions.
|
||||
4. Confirm your project has been analyzed at least once in SonarCloud.
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
description: Containerize a Golang application and monitor it with Prometheus and Grafana.
|
||||
keywords: golang, prometheus, grafana, monitoring, containerize
|
||||
title: Monitor a Golang application with Prometheus and Grafana
|
||||
summary: |
|
||||
Learn how to containerize a Golang application and monitor it with Prometheus and Grafana.
|
||||
linkTitle: Prometheus and Grafana
|
||||
languages: [go]
|
||||
params:
|
||||
time: 45 minutes
|
||||
---
|
||||
|
||||
The guide teaches you how to containerize a Golang application and monitor it with Prometheus and Grafana.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) for his contribution to this guide.
|
||||
|
||||
## Overview
|
||||
|
||||
To make sure your application is working as intended, monitoring is important. One of the most popular monitoring tools is Prometheus. Prometheus is an open-source monitoring and alerting toolkit that is designed for reliability and scalability. It collects metrics from monitored targets by scraping metrics HTTP endpoints on these targets. To visualize the metrics, you can use Grafana. Grafana is an open-source platform for monitoring and observability that allows you to query, visualize, alert on, and understand your metrics no matter where they are stored.
|
||||
|
||||
In this guide, you will be creating a Golang server with some endpoints to simulate a real-world application. Then you will expose metrics from the server using Prometheus. Finally, you will visualize the metrics using Grafana. You will containerize the Golang application, and using the Docker Compose file, you will connect all the services: Golang, Prometheus, and Grafana.
|
||||
|
||||
## What will you learn?
|
||||
|
||||
* Create a Golang application with custom Prometheus metrics.
|
||||
* Containerize a Golang application.
|
||||
* Use Docker Compose to run multiple services and connect them together to monitor a Golang application with Prometheus and Grafana.
|
||||
* Visualize the metrics using Grafana dashboards.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A good understanding of Golang is assumed.
|
||||
- You must me familiar with Prometheus and creating dashboards in Grafana.
|
||||
- You must have familiarity with Docker concepts like containers, images, and Dockerfiles. If you are new to Docker, you can start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
## Next steps
|
||||
|
||||
You will create a Golang server and expose metrics using Prometheus.
|
||||
@@ -1,250 +0,0 @@
|
||||
---
|
||||
title: Building the application
|
||||
linkTitle: Understand the application
|
||||
weight: 10 #
|
||||
keywords: go, golang, prometheus, grafana, containerize, monitor
|
||||
description: Learn how to create a Golang server to register metrics with Prometheus.
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
You will be creating a Golang server with some endpoints to simulate a real-world application. Then you will expose metrics from the server using Prometheus.
|
||||
|
||||
## Getting the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change
|
||||
directory to a directory that you want to work in, and run the following
|
||||
command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/go-prometheus-monitoring.git
|
||||
```
|
||||
|
||||
Once you cloned you will see the following content structure inside `go-prometheus-monitoring` directory,
|
||||
|
||||
```text
|
||||
go-prometheus-monitoring
|
||||
├── CONTRIBUTING.md
|
||||
├── Docker
|
||||
│ ├── grafana.yml
|
||||
│ └── prometheus.yml
|
||||
├── dashboard.json
|
||||
├── Dockerfile
|
||||
├── LICENSE
|
||||
├── README.md
|
||||
├── compose.yaml
|
||||
├── go.mod
|
||||
├── go.sum
|
||||
└── main.go
|
||||
```
|
||||
|
||||
- **main.go** - The entry point of the application.
|
||||
- **go.mod and go.sum** - Go module files.
|
||||
- **Dockerfile** - Dockerfile used to build the app.
|
||||
- **Docker/** - Contains the Docker Compose configuration files for Grafana and Prometheus.
|
||||
- **compose.yaml** - Compose file to launch everything (Golang app, Prometheus, and Grafana).
|
||||
- **dashboard.json** - Grafana dashboard configuration file.
|
||||
- **Dockerfile** - Dockerfile used to build the Golang app.
|
||||
- **compose.yaml** - Docker Compose file to launch everything (Golang app, Prometheus, and Grafana).
|
||||
- Other files are for licensing and documentation purposes.
|
||||
|
||||
## Understanding the application
|
||||
|
||||
The following is the complete logic of the application you will find in `main.go`.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// Define metrics
|
||||
var (
|
||||
HttpRequestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_total",
|
||||
Help: "Total number of requests processed by the API",
|
||||
}, []string{"path", "status"})
|
||||
|
||||
HttpRequestErrorTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_error_total",
|
||||
Help: "Total number of errors returned by the API",
|
||||
}, []string{"path", "status"})
|
||||
)
|
||||
|
||||
// Custom registry (without default Go metrics)
|
||||
var customRegistry = prometheus.NewRegistry()
|
||||
|
||||
// Register metrics with custom registry
|
||||
func init() {
|
||||
customRegistry.MustRegister(HttpRequestTotal, HttpRequestErrorTotal)
|
||||
}
|
||||
|
||||
func main() {
|
||||
router := gin.Default()
|
||||
|
||||
// Register /metrics before middleware
|
||||
router.GET("/metrics", PrometheusHandler())
|
||||
|
||||
router.Use(RequestMetricsMiddleware())
|
||||
router.GET("/health", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Up and running!",
|
||||
})
|
||||
})
|
||||
router.GET("/v1/users", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Hello from /v1/users",
|
||||
})
|
||||
})
|
||||
|
||||
router.Run(":8000")
|
||||
}
|
||||
|
||||
// Custom metrics handler with custom registry
|
||||
func PrometheusHandler() gin.HandlerFunc {
|
||||
h := promhttp.HandlerFor(customRegistry, promhttp.HandlerOpts{})
|
||||
return func(c *gin.Context) {
|
||||
h.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware to record incoming requests metrics
|
||||
func RequestMetricsMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
path := c.Request.URL.Path
|
||||
c.Next()
|
||||
status := c.Writer.Status()
|
||||
if status < 400 {
|
||||
HttpRequestTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
} else {
|
||||
HttpRequestErrorTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this part of the code, you have imported the required packages `gin`, `prometheus`, and `promhttp`. Then you have defined a couple of variables, `HttpRequestTotal` and `HttpRequestErrorTotal` are Prometheus counter metrics, and `customRegistry` is a custom registry that will be used to register these metrics. The name of the metric is a string that you can use to identify the metric. The help string is a string that will be shown when you query the `/metrics` endpoint to understand the metric. The reason you are using the custom registry is so avoid the default Go metrics that are registered by default by the Prometheus client. Then using the `init` function you are registering the metrics with the custom registry.
|
||||
|
||||
```go
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// Define metrics
|
||||
var (
|
||||
HttpRequestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_total",
|
||||
Help: "Total number of requests processed by the API",
|
||||
}, []string{"path", "status"})
|
||||
|
||||
HttpRequestErrorTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_error_total",
|
||||
Help: "Total number of errors returned by the API",
|
||||
}, []string{"path", "status"})
|
||||
)
|
||||
|
||||
// Custom registry (without default Go metrics)
|
||||
var customRegistry = prometheus.NewRegistry()
|
||||
|
||||
// Register metrics with custom registry
|
||||
func init() {
|
||||
customRegistry.MustRegister(HttpRequestTotal, HttpRequestErrorTotal)
|
||||
}
|
||||
```
|
||||
|
||||
In the `main` function, you have created a new instance of the `gin` framework and created three routes. You can see the health endpoint that is on path `/health` that will return a JSON with `{"message": "Up and running!"}` and the `/v1/users` endpoint that will return a JSON with `{"message": "Hello from /v1/users"}`. The third route is for the `/metrics` endpoint that will return the metrics in the Prometheus format. Then you have `RequestMetricsMiddleware` middleware, it will be called for every request made to the API. It will record the incoming requests metrics like status codes and paths. Finally, you are running the gin application on port 8000.
|
||||
|
||||
```golang
|
||||
func main() {
|
||||
router := gin.Default()
|
||||
|
||||
// Register /metrics before middleware
|
||||
router.GET("/metrics", PrometheusHandler())
|
||||
|
||||
router.Use(RequestMetricsMiddleware())
|
||||
router.GET("/health", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Up and running!",
|
||||
})
|
||||
})
|
||||
router.GET("/v1/users", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Hello from /v1/users",
|
||||
})
|
||||
})
|
||||
|
||||
router.Run(":8000")
|
||||
}
|
||||
```
|
||||
|
||||
Now comes the middleware function `RequestMetricsMiddleware`. This function is called for every request made to the API. It increments the `HttpRequestTotal` counter (different counter for different paths and status codes) if the status code is less than or equal to 400. If the status code is greater than 400, it increments the `HttpRequestErrorTotal` counter (different counter for different paths and status codes). The `PrometheusHandler` function is the custom handler that will be called for the `/metrics` endpoint. It will return the metrics in the Prometheus format.
|
||||
|
||||
```golang
|
||||
// Custom metrics handler with custom registry
|
||||
func PrometheusHandler() gin.HandlerFunc {
|
||||
h := promhttp.HandlerFor(customRegistry, promhttp.HandlerOpts{})
|
||||
return func(c *gin.Context) {
|
||||
h.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware to record incoming requests metrics
|
||||
func RequestMetricsMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
path := c.Request.URL.Path
|
||||
c.Next()
|
||||
status := c.Writer.Status()
|
||||
if status < 400 {
|
||||
HttpRequestTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
} else {
|
||||
HttpRequestErrorTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That's it, this was the complete gist of the application. Now it's time to run and test if the app is registering metrics correctly.
|
||||
|
||||
## Running the application
|
||||
|
||||
Make sure you are still inside `go-prometheus-monitoring` directory in the terminal, and run the following command. Install the dependencies by running `go mod tidy` and then build and run the application by running `go run main.go`. Then visit `http://localhost:8000/health` or `http://localhost:8000/v1/users`. You should see the output `{"message": "Up and running!"}` or `{"message": "Hello from /v1/users"}`. If you are able to see this then your app is successfully up and running.
|
||||
|
||||
|
||||
Now, check your application's metrics by accessing the `/metrics` endpoint.
|
||||
Open `http://localhost:8000/metrics` in your browser. You should see similar output to the following.
|
||||
|
||||
```sh
|
||||
# HELP api_http_request_error_total Total number of errors returned by the API
|
||||
# TYPE api_http_request_error_total counter
|
||||
api_http_request_error_total{path="/",status="404"} 1
|
||||
api_http_request_error_total{path="//v1/users",status="404"} 1
|
||||
api_http_request_error_total{path="/favicon.ico",status="404"} 1
|
||||
# HELP api_http_request_total Total number of requests processed by the API
|
||||
# TYPE api_http_request_total counter
|
||||
api_http_request_total{path="/health",status="200"} 2
|
||||
api_http_request_total{path="/v1/users",status="200"} 1
|
||||
```
|
||||
|
||||
In the terminal, press `ctrl` + `c` to stop the application.
|
||||
|
||||
> [!Note]
|
||||
> If you don't want to run the application locally, and want to run it in a Docker container, skip to next page where you create a Dockerfile and containerize the application.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to create a Golang app to register metrics with Prometheus. By implementing middleware functions, you were able to increment the counters based on the request path and status codes.
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you'll learn how to containerize your application.
|
||||
@@ -1,166 +0,0 @@
|
||||
---
|
||||
title: Connecting services with Docker Compose
|
||||
linkTitle: Connect with Compose
|
||||
weight: 30 #
|
||||
keywords: go, golang, prometheus, grafana, containerize, monitor
|
||||
description: Learn how to connect services with Docker Compose to monitor a Golang application with Prometheus and Grafana.
|
||||
---
|
||||
|
||||
Now that you have containerized the Golang application, you will use Docker Compose to connect your services together. You will connect the Golang application, Prometheus, and Grafana services together to monitor the Golang application with Prometheus and Grafana.
|
||||
|
||||
## Creating a Docker Compose file
|
||||
|
||||
Create a new file named `compose.yml` in the root directory of your Golang application. The Docker Compose file contains instructions to run multiple services and connect them together.
|
||||
|
||||
Here is a Docker Compose file for a project that uses Golang, Prometheus, and Grafana. You will also find this file in the `go-prometheus-monitoring` directory.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
api:
|
||||
container_name: go-api
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: go-api:latest
|
||||
ports:
|
||||
- 8000:8000
|
||||
networks:
|
||||
- go-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
develop:
|
||||
watch:
|
||||
- path: .
|
||||
action: rebuild
|
||||
|
||||
prometheus:
|
||||
container_name: prometheus
|
||||
image: prom/prometheus:v2.55.0
|
||||
volumes:
|
||||
- ./Docker/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
ports:
|
||||
- 9090:9090
|
||||
networks:
|
||||
- go-network
|
||||
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana:11.3.0
|
||||
volumes:
|
||||
- ./Docker/grafana.yml:/etc/grafana/provisioning/datasources/datasource.yaml
|
||||
- grafana-data:/var/lib/grafana
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
- go-network
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=password
|
||||
|
||||
volumes:
|
||||
grafana-data:
|
||||
|
||||
networks:
|
||||
go-network:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
## Understanding the Docker Compose file
|
||||
|
||||
The Docker Compose file consists of three services:
|
||||
|
||||
- **Golang application service**: This service builds the Golang application using the Dockerfile and runs it in a container. It exposes the application's port `8000` and connects to the `go-network` network. It also defines a health check to monitor the application's health. You have also used `healthcheck` to monitor the health of the application. The health check runs every 30 seconds and retries 5 times if the health check fails. The health check uses the `curl` command to check the `/health` endpoint of the application. Apart from the health check, you have also added a `develop` section to watch the changes in the application's source code and rebuild the application using the Docker Compose Watch feature.
|
||||
|
||||
- **Prometheus service**: This service runs the Prometheus server in a container. It uses the official Prometheus image `prom/prometheus:v2.55.0`. It exposes the Prometheus server on port `9090` and connects to the `go-network` network. You have also mounted the `prometheus.yml` file from the `Docker` directory which is present in the root directory of your project. The `prometheus.yml` file contains the Prometheus configuration to scrape the metrics from the Golang application. This is how you connect the Prometheus server to the Golang application.
|
||||
|
||||
```yaml
|
||||
global:
|
||||
scrape_interval: 10s
|
||||
evaluation_interval: 10s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: myapp
|
||||
static_configs:
|
||||
- targets: ["api:8000"]
|
||||
```
|
||||
|
||||
In the `prometheus.yml` file, you have defined a job named `myapp` to scrape the metrics from the Golang application. The `targets` field specifies the target to scrape the metrics from. In this case, the target is the Golang application running on port `8000`. The `api` is the service name of the Golang application in the Docker Compose file. The Prometheus server will scrape the metrics from the Golang application every 10 seconds.
|
||||
|
||||
- **Grafana service**: This service runs the Grafana server in a container. It uses the official Grafana image `grafana/grafana:11.3.0`. It exposes the Grafana server on port `3000` and connects to the `go-network` network. You have also mounted the `grafana.yml` file from the `Docker` directory which is present in the root directory of your project. The `grafana.yml` file contains the Grafana configuration to add the Prometheus data source. This is how you connect the Grafana server to the Prometheus server. In the environment variables, you have set the Grafana admin user and password, which will be used to log in to the Grafana dashboard.
|
||||
|
||||
```yaml
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
- name: Prometheus (Main)
|
||||
type: prometheus
|
||||
url: http://prometheus:9090
|
||||
isDefault: true
|
||||
```
|
||||
|
||||
In the `grafana.yml` file, you have defined a Prometheus data source named `Prometheus (Main)`. The `type` field specifies the type of the data source, which is `prometheus`. The `url` field specifies the URL of the Prometheus server to fetch the metrics from. In this case, the URL is `http://prometheus:9090`. `prometheus` is the service name of the Prometheus server in the Docker Compose file. The `isDefault` field specifies whether the data source is the default data source in Grafana.
|
||||
|
||||
Apart from the services, the Docker Compose file also defines a volume named `grafana-data` to persist the Grafana data and a network named `go-network` to connect the services together. You have created a custom network `go-network` to connect the services together. The `driver: bridge` field specifies the network driver to use for the network.
|
||||
|
||||
## Building and running the services
|
||||
|
||||
Now that you have the Docker Compose file, you can build the services and run them together using Docker Compose.
|
||||
|
||||
To build and run the services, run the following command in the terminal:
|
||||
|
||||
```console
|
||||
$ docker compose up
|
||||
```
|
||||
|
||||
The `docker compose up` command builds the services defined in the Docker Compose file and runs them together. You will see the similar output in the terminal:
|
||||
|
||||
```console
|
||||
✔ Network go-prometheus-monitoring_go-network Created 0.0s
|
||||
✔ Container grafana Created 0.3s
|
||||
✔ Container go-api Created 0.2s
|
||||
✔ Container prometheus Created 0.3s
|
||||
Attaching to go-api, grafana, prometheus
|
||||
go-api | [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
go-api |
|
||||
go-api | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
go-api | - using env: export GIN_MODE=release
|
||||
go-api | - using code: gin.SetMode(gin.ReleaseMode)
|
||||
go-api |
|
||||
go-api | [GIN-debug] GET /metrics --> main.PrometheusHandler.func1 (3 handlers)
|
||||
go-api | [GIN-debug] GET /health --> main.main.func1 (4 handlers)
|
||||
go-api | [GIN-debug] GET /v1/users --> main.main.func2 (4 handlers)
|
||||
go-api | [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
|
||||
go-api | Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
|
||||
go-api | [GIN-debug] Listening and serving HTTP on :8000
|
||||
prometheus | ts=2025-03-15T05:57:06.676Z caller=main.go:627 level=info msg="No time or size retention was set so using the default time retention" duration=15d
|
||||
prometheus | ts=2025-03-15T05:57:06.678Z caller=main.go:671 level=info msg="Starting Prometheus Server" mode=server version="(version=2.55.0, branch=HEAD, revision=91d80252c3e528728b0f88d254dd720f6be07cb8)"
|
||||
grafana | logger=settings t=2025-03-15T05:57:06.865335506Z level=info msg="Config overridden from command line" arg="default.log.mode=console"
|
||||
grafana | logger=settings t=2025-03-15T05:57:06.865337131Z level=info msg="Config overridden from Environment variable" var="GF_PATHS_DATA=/var/lib/grafana"
|
||||
grafana | logger=ngalert.state.manager t=2025-03-15T05:57:07.088956839Z level=info msg="State
|
||||
.
|
||||
.
|
||||
grafana | logger=plugin.angulardetectorsprovider.dynamic t=2025-03-15T05:57:07.530317298Z level=info msg="Patterns update finished" duration=440.489125ms
|
||||
```
|
||||
|
||||
The services will start running, and you can access the Golang application at `http://localhost:8000`, Prometheus at `http://localhost:9090/health`, and Grafana at `http://localhost:3000`. You can also check the running containers using the `docker ps` command.
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to connect services together using Docker Compose. You created a Docker Compose file to run multiple services together and connect them using networks. You also learned how to build and run the services using Docker Compose.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Docker Compose overview](/manuals/compose/_index.md)
|
||||
- [Compose file reference](/reference/compose-file/_index.md)
|
||||
|
||||
Next, you will learn how to develop the Golang application with Docker Compose and monitor it with Prometheus and Grafana.
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you will learn how to develop the Golang application with Docker. You will also learn how to use Docker Compose Watch to rebuild the image whenever you make changes to the code. Lastly, you will test the application and visualize the metrics in Grafana using Prometheus as the data source.
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
title: Containerize a Golang application
|
||||
linkTitle: Containerize your app
|
||||
weight: 20
|
||||
keywords: go, golang, containerize, initialize
|
||||
description: Learn how to containerize a Golang application.
|
||||
---
|
||||
|
||||
Containerization helps you bundle the application and its dependencies into a single package called a container. This package can run on any platform without worrying about the environment. In this section, you will learn how to containerize a Golang application using Docker.
|
||||
|
||||
To containerize a Golang application, you first need to create a Dockerfile. The Dockerfile contains instructions to build and run the application in a container. Also, when creating a Dockerfile, you can follow different sets of best practices to optimize the image size and make it more secure.
|
||||
|
||||
## Creating a Dockerfile
|
||||
|
||||
Create a new file named `Dockerfile` in the root directory of your Golang application. The Dockerfile contains instructions to build and run the application in a container.
|
||||
|
||||
The following is a Dockerfile for a Golang application. You will also find this file in the `go-prometheus-monitoring` directory.
|
||||
|
||||
```dockerfile
|
||||
# Use the official Golang image as the base
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
# Set environment variables
|
||||
ENV CGO_ENABLED=0 \
|
||||
GOOS=linux \
|
||||
GOARCH=amd64
|
||||
|
||||
# Set working directory inside the container
|
||||
WORKDIR /build
|
||||
|
||||
# Copy go.mod and go.sum files for dependency installation
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
# Download dependencies
|
||||
RUN go mod download
|
||||
|
||||
# Copy the entire application source
|
||||
COPY . .
|
||||
|
||||
# Build the Go binary
|
||||
RUN go build -o /app .
|
||||
|
||||
# Final lightweight stage
|
||||
FROM alpine:3.21 AS final
|
||||
|
||||
# Copy the compiled binary from the builder stage
|
||||
COPY --from=builder /app /bin/app
|
||||
|
||||
# Expose the application's port
|
||||
EXPOSE 8000
|
||||
|
||||
# Run the application
|
||||
CMD ["bin/app"]
|
||||
```
|
||||
|
||||
## Understanding the Dockerfile
|
||||
|
||||
The Dockerfile consists of two stages:
|
||||
|
||||
1. **Build stage**: This stage uses the official Golang image as the base and sets the necessary environment variables. It also sets the working directory inside the container, copies the `go.mod` and `go.sum` files for dependency installation, downloads the dependencies, copies the entire application source, and builds the Go binary.
|
||||
|
||||
You use the `golang:1.24-alpine` image as the base image for the build stage. The `CGO_ENABLED=0` environment variable disables CGO, which is useful for building static binaries. You also set the `GOOS` and `GOARCH` environment variables to `linux` and `amd64`, respectively, to build the binary for the Linux platform.
|
||||
|
||||
2. **Final stage**: This stage uses the official Alpine image as the base and copies the compiled binary from the build stage. It also exposes the application's port and runs the application.
|
||||
|
||||
You use the `alpine:3.21` image as the base image for the final stage. You copy the compiled binary from the build stage to the final image. You expose the application's port using the `EXPOSE` instruction and run the application using the `CMD` instruction.
|
||||
|
||||
Apart from the multi-stage build, the Dockerfile also follows best practices such as using the official images, setting the working directory, and copying only the necessary files to the final image. You can further optimize the Dockerfile by other best practices.
|
||||
|
||||
## Build the Docker image and run the application
|
||||
|
||||
One you have the Dockerfile, you can build the Docker image and run the application in a container.
|
||||
|
||||
To build the Docker image, run the following command in the terminal:
|
||||
|
||||
```console
|
||||
$ docker build -t go-api:latest .
|
||||
```
|
||||
|
||||
After building the image, you can run the application in a container using the following command:
|
||||
|
||||
```console
|
||||
$ docker run -p 8000:8000 go-api:latest
|
||||
```
|
||||
|
||||
The application will start running inside the container, and you can access it at `http://localhost:8000`. You can also check the running containers using the `docker ps` command.
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
```
|
||||
|
||||
## Summary
|
||||
|
||||
In this section, you learned how to containerize a Golang application using a Dockerfile. You created a multi-stage Dockerfile to build and run the application in a container. You also learned about best practices to optimize the Docker image size and make it more secure.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Dockerfile reference](/reference/dockerfile.md)
|
||||
- [.dockerignore file](/reference/dockerfile.md#dockerignore-file)
|
||||
|
||||
## Next steps
|
||||
|
||||
In the next section, you will learn how to use Docker Compose to connect and run multiple services together to monitor a Golang application with Prometheus and Grafana.
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
title: Developing your application
|
||||
linkTitle: Develop your app
|
||||
weight: 40
|
||||
keywords: go, golang, containerize, initialize
|
||||
description: Learn how to develop the Golang application with Docker.
|
||||
---
|
||||
|
||||
In the last section, you saw how using Docker Compose, you can connect your services together. In this section, you will learn how to develop the Golang application with Docker. You will also see how to use Docker Compose Watch to rebuild the image whenever you make changes to the code. Lastly, you will test the application and visualize the metrics in Grafana using Prometheus as the data source.
|
||||
|
||||
## Developing the application
|
||||
|
||||
Now, if you make any changes to your Golang application locally, it needs to reflect in the container, right? To do that, one approach is use the `--build` flag in Docker Compose after making changes in the code. This will rebuild all the services which have the `build` instruction in the `compose.yml` file, in your case, the `api` service (Golang application).
|
||||
|
||||
```console
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
But, this is not the best approach. This is not efficient. Every time you make a change in the code, you need to rebuild manually. This is not is not a good flow for development.
|
||||
|
||||
The better approach is to use Docker Compose Watch. In the `compose.yml` file, under the service `api`, you have added the `develop` section. So, it's more like a hot reloading. Whenever you make changes to code (defined in `path`), it will rebuild the image (or restart depending on the action). This is how you can use it:
|
||||
|
||||
```yaml {hl_lines="17-20",linenos=true}
|
||||
services:
|
||||
api:
|
||||
container_name: go-api
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: go-api:latest
|
||||
ports:
|
||||
- 8000:8000
|
||||
networks:
|
||||
- go-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
develop:
|
||||
watch:
|
||||
- path: .
|
||||
action: rebuild
|
||||
```
|
||||
|
||||
Once you have added the `develop` section in the `compose.yml` file, you can use the following command to start the development server:
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `main.go` or any other file in the project, the `api` service will be rebuilt automatically. You will see the following output in the terminal:
|
||||
|
||||
```bash
|
||||
Rebuilding service(s) ["api"] after changes were detected...
|
||||
[+] Building 8.1s (15/15) FINISHED docker:desktop-linux
|
||||
=> [api internal] load build definition from Dockerfile 0.0s
|
||||
=> => transferring dockerfile: 704B 0.0s
|
||||
=> [api internal] load metadata for docker.io/library/alpine:3.17 1.1s
|
||||
.
|
||||
=> => exporting manifest list sha256:89ebc86fd51e27c1da440dc20858ff55fe42211a1930c2d51bbdce09f430c7f1 0.0s
|
||||
=> => naming to docker.io/library/go-api:latest 0.0s
|
||||
=> => unpacking to docker.io/library/go-api:latest 0.0s
|
||||
=> [api] resolving provenance for metadata file 0.0s
|
||||
service(s) ["api"] successfully built
|
||||
```
|
||||
|
||||
## Testing the application
|
||||
|
||||
Now that you have your application running, head over to the Grafana dashboard to visualize the metrics you are registering. Open your browser and navigate to `http://localhost:3000`. You will be greeted with the Grafana login page. The login credentials are the ones provided in Compose file.
|
||||
|
||||
Once you are logged in, you can create a new dashboard. While creating dashboard you will notice that is default data source is `Prometheus`. This is because you have already configured the data source in the `grafana.yml` file.
|
||||
|
||||

|
||||
|
||||
You can use different panels to visualize the metrics. This guide doesn't go into details of Grafana. You can refer to the [Grafana documentation](https://grafana.com/docs/grafana/latest/) for more information. There is a Bar Gauge panel to visualize the total number of requests from different endpoints. You used the `api_http_request_total` and `api_http_request_error_total` metrics to get the data.
|
||||
|
||||

|
||||
|
||||
You created this panel to visualize the total number of requests from different endpoints to compare the successful and failed requests. For all the good requests, the bar will be green, and for all the failed requests, the bar will be red. Plus it will also show the from which endpoint the request is coming, either it's a successful request or a failed request. If you want to use this panel, you can import the `dashboard.json` file from the repository you cloned.
|
||||
|
||||
## Summary
|
||||
|
||||
You've come to the end of this guide. You learned how to develop the Golang application with Docker. You also saw how to use Docker Compose Watch to rebuild the image whenever you make changes to the code. Lastly, you tested the application and visualized the metrics in Grafana using Prometheus as the data source.
|
||||
629
content/guides/go-prometheus-monitoring/index.md
Normal file
629
content/guides/go-prometheus-monitoring/index.md
Normal file
@@ -0,0 +1,629 @@
|
||||
---
|
||||
description: Containerize a Golang application and monitor it with Prometheus and Grafana.
|
||||
keywords: golang, prometheus, grafana, monitoring, containerize
|
||||
title: Monitor a Golang application with Prometheus and Grafana
|
||||
summary: |
|
||||
Learn how to containerize a Golang application and monitor it with Prometheus and Grafana.
|
||||
linkTitle: Prometheus and Grafana
|
||||
aliases:
|
||||
- /guides/go-prometheus-monitoring/application/
|
||||
- /guides/go-prometheus-monitoring/compose/
|
||||
- /guides/go-prometheus-monitoring/containerize/
|
||||
- /guides/go-prometheus-monitoring/develop/
|
||||
params:
|
||||
tags: [cicd]
|
||||
time: 45 minutes
|
||||
---
|
||||
|
||||
|
||||
The guide teaches you how to containerize a Golang application and monitor it with Prometheus and Grafana.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Pradumna Saraf](https://twitter.com/pradumna_saraf) for his contribution to this guide.
|
||||
|
||||
## Overview
|
||||
|
||||
To make sure your application is working as intended, monitoring is important. One of the most popular monitoring tools is Prometheus. Prometheus is an open-source monitoring and alerting toolkit that is designed for reliability and scalability. It collects metrics from monitored targets by scraping metrics HTTP endpoints on these targets. To visualize the metrics, you can use Grafana. Grafana is an open-source platform for monitoring and observability that allows you to query, visualize, alert on, and understand your metrics no matter where they are stored.
|
||||
|
||||
In this guide, you will be creating a Golang server with some endpoints to simulate a real-world application. Then you will expose metrics from the server using Prometheus. Finally, you will visualize the metrics using Grafana. You will containerize the Golang application, and using the Docker Compose file, you will connect all the services: Golang, Prometheus, and Grafana.
|
||||
|
||||
## What will you learn?
|
||||
|
||||
* Create a Golang application with custom Prometheus metrics.
|
||||
* Containerize a Golang application.
|
||||
* Use Docker Compose to run multiple services and connect them together to monitor a Golang application with Prometheus and Grafana.
|
||||
* Visualize the metrics using Grafana dashboards.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A good understanding of Golang is assumed.
|
||||
- You must me familiar with Prometheus and creating dashboards in Grafana.
|
||||
- You must have familiarity with Docker concepts like containers, images, and Dockerfiles. If you are new to Docker, you can start with the [Docker basics](/get-started/docker-concepts/the-basics/what-is-a-container.md) guide.
|
||||
|
||||
## Next steps
|
||||
|
||||
You will create a Golang server and expose metrics using Prometheus.
|
||||
|
||||
## Building the application
|
||||
|
||||
### Prerequisites
|
||||
|
||||
* You have a [Git client](https://git-scm.com/downloads). The examples in this section use a command-line based Git client, but you can use any client.
|
||||
|
||||
You will be creating a Golang server with some endpoints to simulate a real-world application. Then you will expose metrics from the server using Prometheus.
|
||||
|
||||
### Getting the sample application
|
||||
|
||||
Clone the sample application to use with this guide. Open a terminal, change
|
||||
directory to a directory that you want to work in, and run the following
|
||||
command to clone the repository:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/go-prometheus-monitoring.git
|
||||
```
|
||||
|
||||
Once you cloned you will see the following content structure inside `go-prometheus-monitoring` directory,
|
||||
|
||||
```text
|
||||
go-prometheus-monitoring
|
||||
├── CONTRIBUTING.md
|
||||
├── Docker
|
||||
│ ├── grafana.yml
|
||||
│ └── prometheus.yml
|
||||
├── dashboard.json
|
||||
├── Dockerfile
|
||||
├── LICENSE
|
||||
├── README.md
|
||||
├── compose.yaml
|
||||
├── go.mod
|
||||
├── go.sum
|
||||
└── main.go
|
||||
```
|
||||
|
||||
- **main.go** - The entry point of the application.
|
||||
- **go.mod and go.sum** - Go module files.
|
||||
- **Dockerfile** - Dockerfile used to build the app.
|
||||
- **Docker/** - Contains the Docker Compose configuration files for Grafana and Prometheus.
|
||||
- **compose.yaml** - Compose file to launch everything (Golang app, Prometheus, and Grafana).
|
||||
- **dashboard.json** - Grafana dashboard configuration file.
|
||||
- **Dockerfile** - Dockerfile used to build the Golang app.
|
||||
- **compose.yaml** - Docker Compose file to launch everything (Golang app, Prometheus, and Grafana).
|
||||
- Other files are for licensing and documentation purposes.
|
||||
|
||||
### Understanding the application
|
||||
|
||||
The following is the complete logic of the application you will find in `main.go`.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// Define metrics
|
||||
var (
|
||||
HttpRequestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_total",
|
||||
Help: "Total number of requests processed by the API",
|
||||
}, []string{"path", "status"})
|
||||
|
||||
HttpRequestErrorTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_error_total",
|
||||
Help: "Total number of errors returned by the API",
|
||||
}, []string{"path", "status"})
|
||||
)
|
||||
|
||||
// Custom registry (without default Go metrics)
|
||||
var customRegistry = prometheus.NewRegistry()
|
||||
|
||||
// Register metrics with custom registry
|
||||
func init() {
|
||||
customRegistry.MustRegister(HttpRequestTotal, HttpRequestErrorTotal)
|
||||
}
|
||||
|
||||
func main() {
|
||||
router := gin.Default()
|
||||
|
||||
// Register /metrics before middleware
|
||||
router.GET("/metrics", PrometheusHandler())
|
||||
|
||||
router.Use(RequestMetricsMiddleware())
|
||||
router.GET("/health", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Up and running!",
|
||||
})
|
||||
})
|
||||
router.GET("/v1/users", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Hello from /v1/users",
|
||||
})
|
||||
})
|
||||
|
||||
router.Run(":8000")
|
||||
}
|
||||
|
||||
// Custom metrics handler with custom registry
|
||||
func PrometheusHandler() gin.HandlerFunc {
|
||||
h := promhttp.HandlerFor(customRegistry, promhttp.HandlerOpts{})
|
||||
return func(c *gin.Context) {
|
||||
h.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware to record incoming requests metrics
|
||||
func RequestMetricsMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
path := c.Request.URL.Path
|
||||
c.Next()
|
||||
status := c.Writer.Status()
|
||||
if status < 400 {
|
||||
HttpRequestTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
} else {
|
||||
HttpRequestErrorTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this part of the code, you have imported the required packages `gin`, `prometheus`, and `promhttp`. Then you have defined a couple of variables, `HttpRequestTotal` and `HttpRequestErrorTotal` are Prometheus counter metrics, and `customRegistry` is a custom registry that will be used to register these metrics. The name of the metric is a string that you can use to identify the metric. The help string is a string that will be shown when you query the `/metrics` endpoint to understand the metric. The reason you are using the custom registry is so avoid the default Go metrics that are registered by default by the Prometheus client. Then using the `init` function you are registering the metrics with the custom registry.
|
||||
|
||||
```go
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// Define metrics
|
||||
var (
|
||||
HttpRequestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_total",
|
||||
Help: "Total number of requests processed by the API",
|
||||
}, []string{"path", "status"})
|
||||
|
||||
HttpRequestErrorTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Name: "api_http_request_error_total",
|
||||
Help: "Total number of errors returned by the API",
|
||||
}, []string{"path", "status"})
|
||||
)
|
||||
|
||||
// Custom registry (without default Go metrics)
|
||||
var customRegistry = prometheus.NewRegistry()
|
||||
|
||||
// Register metrics with custom registry
|
||||
func init() {
|
||||
customRegistry.MustRegister(HttpRequestTotal, HttpRequestErrorTotal)
|
||||
}
|
||||
```
|
||||
|
||||
In the `main` function, you have created a new instance of the `gin` framework and created three routes. You can see the health endpoint that is on path `/health` that will return a JSON with `{"message": "Up and running!"}` and the `/v1/users` endpoint that will return a JSON with `{"message": "Hello from /v1/users"}`. The third route is for the `/metrics` endpoint that will return the metrics in the Prometheus format. Then you have `RequestMetricsMiddleware` middleware, it will be called for every request made to the API. It will record the incoming requests metrics like status codes and paths. Finally, you are running the gin application on port 8000.
|
||||
|
||||
```golang
|
||||
func main() {
|
||||
router := gin.Default()
|
||||
|
||||
// Register /metrics before middleware
|
||||
router.GET("/metrics", PrometheusHandler())
|
||||
|
||||
router.Use(RequestMetricsMiddleware())
|
||||
router.GET("/health", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Up and running!",
|
||||
})
|
||||
})
|
||||
router.GET("/v1/users", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "Hello from /v1/users",
|
||||
})
|
||||
})
|
||||
|
||||
router.Run(":8000")
|
||||
}
|
||||
```
|
||||
|
||||
Now comes the middleware function `RequestMetricsMiddleware`. This function is called for every request made to the API. It increments the `HttpRequestTotal` counter (different counter for different paths and status codes) if the status code is less than or equal to 400. If the status code is greater than 400, it increments the `HttpRequestErrorTotal` counter (different counter for different paths and status codes). The `PrometheusHandler` function is the custom handler that will be called for the `/metrics` endpoint. It will return the metrics in the Prometheus format.
|
||||
|
||||
```golang
|
||||
// Custom metrics handler with custom registry
|
||||
func PrometheusHandler() gin.HandlerFunc {
|
||||
h := promhttp.HandlerFor(customRegistry, promhttp.HandlerOpts{})
|
||||
return func(c *gin.Context) {
|
||||
h.ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware to record incoming requests metrics
|
||||
func RequestMetricsMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
path := c.Request.URL.Path
|
||||
c.Next()
|
||||
status := c.Writer.Status()
|
||||
if status < 400 {
|
||||
HttpRequestTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
} else {
|
||||
HttpRequestErrorTotal.WithLabelValues(path, strconv.Itoa(status)).Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
That's it, this was the complete gist of the application. Now it's time to run and test if the app is registering metrics correctly.
|
||||
|
||||
### Running the application
|
||||
|
||||
Make sure you are still inside `go-prometheus-monitoring` directory in the terminal, and run the following command. Install the dependencies by running `go mod tidy` and then build and run the application by running `go run main.go`. Then visit `http://localhost:8000/health` or `http://localhost:8000/v1/users`. You should see the output `{"message": "Up and running!"}` or `{"message": "Hello from /v1/users"}`. If you are able to see this then your app is successfully up and running.
|
||||
|
||||
|
||||
Now, check your application's metrics by accessing the `/metrics` endpoint.
|
||||
Open `http://localhost:8000/metrics` in your browser. You should see similar output to the following.
|
||||
|
||||
```sh
|
||||
# HELP api_http_request_error_total Total number of errors returned by the API
|
||||
# TYPE api_http_request_error_total counter
|
||||
api_http_request_error_total{path="/",status="404"} 1
|
||||
api_http_request_error_total{path="//v1/users",status="404"} 1
|
||||
api_http_request_error_total{path="/favicon.ico",status="404"} 1
|
||||
# HELP api_http_request_total Total number of requests processed by the API
|
||||
# TYPE api_http_request_total counter
|
||||
api_http_request_total{path="/health",status="200"} 2
|
||||
api_http_request_total{path="/v1/users",status="200"} 1
|
||||
```
|
||||
|
||||
In the terminal, press `ctrl` + `c` to stop the application.
|
||||
|
||||
> [!Note]
|
||||
> If you don't want to run the application locally, and want to run it in a Docker container, skip to next page where you create a Dockerfile and containerize the application.
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you learned how to create a Golang app to register metrics with Prometheus. By implementing middleware functions, you were able to increment the counters based on the request path and status codes.
|
||||
|
||||
### Next steps
|
||||
|
||||
In the next section, you'll learn how to containerize your application.
|
||||
|
||||
## Containerize a Golang application
|
||||
|
||||
Containerization helps you bundle the application and its dependencies into a single package called a container. This package can run on any platform without worrying about the environment. In this section, you will learn how to containerize a Golang application using Docker.
|
||||
|
||||
To containerize a Golang application, you first need to create a Dockerfile. The Dockerfile contains instructions to build and run the application in a container. Also, when creating a Dockerfile, you can follow different sets of best practices to optimize the image size and make it more secure.
|
||||
|
||||
### Creating a Dockerfile
|
||||
|
||||
Create a new file named `Dockerfile` in the root directory of your Golang application. The Dockerfile contains instructions to build and run the application in a container.
|
||||
|
||||
The following is a Dockerfile for a Golang application. You will also find this file in the `go-prometheus-monitoring` directory.
|
||||
|
||||
```dockerfile
|
||||
# Use the official Golang image as the base
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
# Set environment variables
|
||||
ENV CGO_ENABLED=0 \
|
||||
GOOS=linux \
|
||||
GOARCH=amd64
|
||||
|
||||
# Set working directory inside the container
|
||||
WORKDIR /build
|
||||
|
||||
# Copy go.mod and go.sum files for dependency installation
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
# Download dependencies
|
||||
RUN go mod download
|
||||
|
||||
# Copy the entire application source
|
||||
COPY . .
|
||||
|
||||
# Build the Go binary
|
||||
RUN go build -o /app .
|
||||
|
||||
# Final lightweight stage
|
||||
FROM alpine:3.21 AS final
|
||||
|
||||
# Copy the compiled binary from the builder stage
|
||||
COPY --from=builder /app /bin/app
|
||||
|
||||
# Expose the application's port
|
||||
EXPOSE 8000
|
||||
|
||||
# Run the application
|
||||
CMD ["bin/app"]
|
||||
```
|
||||
|
||||
### Understanding the Dockerfile
|
||||
|
||||
The Dockerfile consists of two stages:
|
||||
|
||||
1. **Build stage**: This stage uses the official Golang image as the base and sets the necessary environment variables. It also sets the working directory inside the container, copies the `go.mod` and `go.sum` files for dependency installation, downloads the dependencies, copies the entire application source, and builds the Go binary.
|
||||
|
||||
You use the `golang:1.24-alpine` image as the base image for the build stage. The `CGO_ENABLED=0` environment variable disables CGO, which is useful for building static binaries. You also set the `GOOS` and `GOARCH` environment variables to `linux` and `amd64`, respectively, to build the binary for the Linux platform.
|
||||
|
||||
2. **Final stage**: This stage uses the official Alpine image as the base and copies the compiled binary from the build stage. It also exposes the application's port and runs the application.
|
||||
|
||||
You use the `alpine:3.21` image as the base image for the final stage. You copy the compiled binary from the build stage to the final image. You expose the application's port using the `EXPOSE` instruction and run the application using the `CMD` instruction.
|
||||
|
||||
Apart from the multi-stage build, the Dockerfile also follows best practices such as using the official images, setting the working directory, and copying only the necessary files to the final image. You can further optimize the Dockerfile by other best practices.
|
||||
|
||||
### Build the Docker image and run the application
|
||||
|
||||
One you have the Dockerfile, you can build the Docker image and run the application in a container.
|
||||
|
||||
To build the Docker image, run the following command in the terminal:
|
||||
|
||||
```console
|
||||
$ docker build -t go-api:latest .
|
||||
```
|
||||
|
||||
After building the image, you can run the application in a container using the following command:
|
||||
|
||||
```console
|
||||
$ docker run -p 8000:8000 go-api:latest
|
||||
```
|
||||
|
||||
The application will start running inside the container, and you can access it at `http://localhost:8000`. You can also check the running containers using the `docker ps` command.
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
```
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you learned how to containerize a Golang application using a Dockerfile. You created a multi-stage Dockerfile to build and run the application in a container. You also learned about best practices to optimize the Docker image size and make it more secure.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Dockerfile reference](/reference/dockerfile.md)
|
||||
- [.dockerignore file](/reference/dockerfile.md#dockerignore-file)
|
||||
|
||||
### Next steps
|
||||
|
||||
In the next section, you will learn how to use Docker Compose to connect and run multiple services together to monitor a Golang application with Prometheus and Grafana.
|
||||
|
||||
## Connecting services with Docker Compose
|
||||
|
||||
Now that you have containerized the Golang application, you will use Docker Compose to connect your services together. You will connect the Golang application, Prometheus, and Grafana services together to monitor the Golang application with Prometheus and Grafana.
|
||||
|
||||
### Creating a Docker Compose file
|
||||
|
||||
Create a new file named `compose.yml` in the root directory of your Golang application. The Docker Compose file contains instructions to run multiple services and connect them together.
|
||||
|
||||
Here is a Docker Compose file for a project that uses Golang, Prometheus, and Grafana. You will also find this file in the `go-prometheus-monitoring` directory.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
api:
|
||||
container_name: go-api
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: go-api:latest
|
||||
ports:
|
||||
- 8000:8000
|
||||
networks:
|
||||
- go-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
develop:
|
||||
watch:
|
||||
- path: .
|
||||
action: rebuild
|
||||
|
||||
prometheus:
|
||||
container_name: prometheus
|
||||
image: prom/prometheus:v2.55.0
|
||||
volumes:
|
||||
- ./Docker/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
ports:
|
||||
- 9090:9090
|
||||
networks:
|
||||
- go-network
|
||||
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana:11.3.0
|
||||
volumes:
|
||||
- ./Docker/grafana.yml:/etc/grafana/provisioning/datasources/datasource.yaml
|
||||
- grafana-data:/var/lib/grafana
|
||||
ports:
|
||||
- 3000:3000
|
||||
networks:
|
||||
- go-network
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=password
|
||||
|
||||
volumes:
|
||||
grafana-data:
|
||||
|
||||
networks:
|
||||
go-network:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
### Understanding the Docker Compose file
|
||||
|
||||
The Docker Compose file consists of three services:
|
||||
|
||||
- **Golang application service**: This service builds the Golang application using the Dockerfile and runs it in a container. It exposes the application's port `8000` and connects to the `go-network` network. It also defines a health check to monitor the application's health. You have also used `healthcheck` to monitor the health of the application. The health check runs every 30 seconds and retries 5 times if the health check fails. The health check uses the `curl` command to check the `/health` endpoint of the application. Apart from the health check, you have also added a `develop` section to watch the changes in the application's source code and rebuild the application using the Docker Compose Watch feature.
|
||||
|
||||
- **Prometheus service**: This service runs the Prometheus server in a container. It uses the official Prometheus image `prom/prometheus:v2.55.0`. It exposes the Prometheus server on port `9090` and connects to the `go-network` network. You have also mounted the `prometheus.yml` file from the `Docker` directory which is present in the root directory of your project. The `prometheus.yml` file contains the Prometheus configuration to scrape the metrics from the Golang application. This is how you connect the Prometheus server to the Golang application.
|
||||
|
||||
```yaml
|
||||
global:
|
||||
scrape_interval: 10s
|
||||
evaluation_interval: 10s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: myapp
|
||||
static_configs:
|
||||
- targets: ["api:8000"]
|
||||
```
|
||||
|
||||
In the `prometheus.yml` file, you have defined a job named `myapp` to scrape the metrics from the Golang application. The `targets` field specifies the target to scrape the metrics from. In this case, the target is the Golang application running on port `8000`. The `api` is the service name of the Golang application in the Docker Compose file. The Prometheus server will scrape the metrics from the Golang application every 10 seconds.
|
||||
|
||||
- **Grafana service**: This service runs the Grafana server in a container. It uses the official Grafana image `grafana/grafana:11.3.0`. It exposes the Grafana server on port `3000` and connects to the `go-network` network. You have also mounted the `grafana.yml` file from the `Docker` directory which is present in the root directory of your project. The `grafana.yml` file contains the Grafana configuration to add the Prometheus data source. This is how you connect the Grafana server to the Prometheus server. In the environment variables, you have set the Grafana admin user and password, which will be used to log in to the Grafana dashboard.
|
||||
|
||||
```yaml
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
- name: Prometheus (Main)
|
||||
type: prometheus
|
||||
url: http://prometheus:9090
|
||||
isDefault: true
|
||||
```
|
||||
|
||||
In the `grafana.yml` file, you have defined a Prometheus data source named `Prometheus (Main)`. The `type` field specifies the type of the data source, which is `prometheus`. The `url` field specifies the URL of the Prometheus server to fetch the metrics from. In this case, the URL is `http://prometheus:9090`. `prometheus` is the service name of the Prometheus server in the Docker Compose file. The `isDefault` field specifies whether the data source is the default data source in Grafana.
|
||||
|
||||
Apart from the services, the Docker Compose file also defines a volume named `grafana-data` to persist the Grafana data and a network named `go-network` to connect the services together. You have created a custom network `go-network` to connect the services together. The `driver: bridge` field specifies the network driver to use for the network.
|
||||
|
||||
### Building and running the services
|
||||
|
||||
Now that you have the Docker Compose file, you can build the services and run them together using Docker Compose.
|
||||
|
||||
To build and run the services, run the following command in the terminal:
|
||||
|
||||
```console
|
||||
$ docker compose up
|
||||
```
|
||||
|
||||
The `docker compose up` command builds the services defined in the Docker Compose file and runs them together. You will see the similar output in the terminal:
|
||||
|
||||
```console
|
||||
✔ Network go-prometheus-monitoring_go-network Created 0.0s
|
||||
✔ Container grafana Created 0.3s
|
||||
✔ Container go-api Created 0.2s
|
||||
✔ Container prometheus Created 0.3s
|
||||
Attaching to go-api, grafana, prometheus
|
||||
go-api | [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
|
||||
go-api |
|
||||
go-api | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
|
||||
go-api | - using env: export GIN_MODE=release
|
||||
go-api | - using code: gin.SetMode(gin.ReleaseMode)
|
||||
go-api |
|
||||
go-api | [GIN-debug] GET /metrics --> main.PrometheusHandler.func1 (3 handlers)
|
||||
go-api | [GIN-debug] GET /health --> main.main.func1 (4 handlers)
|
||||
go-api | [GIN-debug] GET /v1/users --> main.main.func2 (4 handlers)
|
||||
go-api | [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
|
||||
go-api | Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
|
||||
go-api | [GIN-debug] Listening and serving HTTP on :8000
|
||||
prometheus | ts=2025-03-15T05:57:06.676Z caller=main.go:627 level=info msg="No time or size retention was set so using the default time retention" duration=15d
|
||||
prometheus | ts=2025-03-15T05:57:06.678Z caller=main.go:671 level=info msg="Starting Prometheus Server" mode=server version="(version=2.55.0, branch=HEAD, revision=91d80252c3e528728b0f88d254dd720f6be07cb8)"
|
||||
grafana | logger=settings t=2025-03-15T05:57:06.865335506Z level=info msg="Config overridden from command line" arg="default.log.mode=console"
|
||||
grafana | logger=settings t=2025-03-15T05:57:06.865337131Z level=info msg="Config overridden from Environment variable" var="GF_PATHS_DATA=/var/lib/grafana"
|
||||
grafana | logger=ngalert.state.manager t=2025-03-15T05:57:07.088956839Z level=info msg="State
|
||||
.
|
||||
.
|
||||
grafana | logger=plugin.angulardetectorsprovider.dynamic t=2025-03-15T05:57:07.530317298Z level=info msg="Patterns update finished" duration=440.489125ms
|
||||
```
|
||||
|
||||
The services will start running, and you can access the Golang application at `http://localhost:8000`, Prometheus at `http://localhost:9090/health`, and Grafana at `http://localhost:3000`. You can also check the running containers using the `docker ps` command.
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
```
|
||||
|
||||
### Summary
|
||||
|
||||
In this section, you learned how to connect services together using Docker Compose. You created a Docker Compose file to run multiple services together and connect them using networks. You also learned how to build and run the services using Docker Compose.
|
||||
|
||||
Related information:
|
||||
|
||||
- [Docker Compose overview](/manuals/compose/_index.md)
|
||||
- [Compose file reference](/reference/compose-file/_index.md)
|
||||
|
||||
Next, you will learn how to develop the Golang application with Docker Compose and monitor it with Prometheus and Grafana.
|
||||
|
||||
### Next steps
|
||||
|
||||
In the next section, you will learn how to develop the Golang application with Docker. You will also learn how to use Docker Compose Watch to rebuild the image whenever you make changes to the code. Lastly, you will test the application and visualize the metrics in Grafana using Prometheus as the data source.
|
||||
|
||||
## Developing your application
|
||||
|
||||
In the last section, you saw how using Docker Compose, you can connect your services together. In this section, you will learn how to develop the Golang application with Docker. You will also see how to use Docker Compose Watch to rebuild the image whenever you make changes to the code. Lastly, you will test the application and visualize the metrics in Grafana using Prometheus as the data source.
|
||||
|
||||
### Developing the application
|
||||
|
||||
Now, if you make any changes to your Golang application locally, it needs to reflect in the container, right? To do that, one approach is use the `--build` flag in Docker Compose after making changes in the code. This will rebuild all the services which have the `build` instruction in the `compose.yml` file, in your case, the `api` service (Golang application).
|
||||
|
||||
```console
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
But, this is not the best approach. This is not efficient. Every time you make a change in the code, you need to rebuild manually. This is not is not a good flow for development.
|
||||
|
||||
The better approach is to use Docker Compose Watch. In the `compose.yml` file, under the service `api`, you have added the `develop` section. So, it's more like a hot reloading. Whenever you make changes to code (defined in `path`), it will rebuild the image (or restart depending on the action). This is how you can use it:
|
||||
|
||||
```yaml {hl_lines="17-20",linenos=true}
|
||||
services:
|
||||
api:
|
||||
container_name: go-api
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: go-api:latest
|
||||
ports:
|
||||
- 8000:8000
|
||||
networks:
|
||||
- go-network
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
develop:
|
||||
watch:
|
||||
- path: .
|
||||
action: rebuild
|
||||
```
|
||||
|
||||
Once you have added the `develop` section in the `compose.yml` file, you can use the following command to start the development server:
|
||||
|
||||
```console
|
||||
$ docker compose watch
|
||||
```
|
||||
|
||||
Now, if you modify your `main.go` or any other file in the project, the `api` service will be rebuilt automatically. You will see the following output in the terminal:
|
||||
|
||||
```bash
|
||||
Rebuilding service(s) ["api"] after changes were detected...
|
||||
[+] Building 8.1s (15/15) FINISHED docker:desktop-linux
|
||||
=> [api internal] load build definition from Dockerfile 0.0s
|
||||
=> => transferring dockerfile: 704B 0.0s
|
||||
=> [api internal] load metadata for docker.io/library/alpine:3.17 1.1s
|
||||
.
|
||||
=> => exporting manifest list sha256:89ebc86fd51e27c1da440dc20858ff55fe42211a1930c2d51bbdce09f430c7f1 0.0s
|
||||
=> => naming to docker.io/library/go-api:latest 0.0s
|
||||
=> => unpacking to docker.io/library/go-api:latest 0.0s
|
||||
=> [api] resolving provenance for metadata file 0.0s
|
||||
service(s) ["api"] successfully built
|
||||
```
|
||||
|
||||
### Testing the application
|
||||
|
||||
Now that you have your application running, head over to the Grafana dashboard to visualize the metrics you are registering. Open your browser and navigate to `http://localhost:3000`. You will be greeted with the Grafana login page. The login credentials are the ones provided in Compose file.
|
||||
|
||||
Once you are logged in, you can create a new dashboard. While creating dashboard you will notice that is default data source is `Prometheus`. This is because you have already configured the data source in the `grafana.yml` file.
|
||||
|
||||

|
||||
|
||||
You can use different panels to visualize the metrics. This guide doesn't go into details of Grafana. You can refer to the [Grafana documentation](https://grafana.com/docs/grafana/latest/) for more information. There is a Bar Gauge panel to visualize the total number of requests from different endpoints. You used the `api_http_request_total` and `api_http_request_error_total` metrics to get the data.
|
||||
|
||||

|
||||
|
||||
You created this panel to visualize the total number of requests from different endpoints to compare the successful and failed requests. For all the good requests, the bar will be green, and for all the failed requests, the bar will be red. Plus it will also show the from which endpoint the request is coming, either it's a successful request or a failed request. If you want to use this panel, you can import the `dashboard.json` file from the repository you cloned.
|
||||
|
||||
### Summary
|
||||
|
||||
You've come to the end of this guide. You learned how to develop the Golang application with Docker. You also saw how to use Docker Compose Watch to rebuild the image whenever you make changes to the code. Lastly, you tested the application and visualized the metrics in Grafana using Prometheus as the data source.
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
title: Go language-specific guide
|
||||
linkTitle: Go
|
||||
description: Containerize Go apps using Docker
|
||||
keywords: docker, getting started, go, golang, language, dockerfile
|
||||
summary: |
|
||||
This guide teaches you how to containerize Go applications using Docker.
|
||||
toc_min: 1
|
||||
toc_max: 2
|
||||
aliases:
|
||||
- /language/golang/
|
||||
- /guides/language/golang/
|
||||
- /guides/golang/configure-ci-cd/
|
||||
- /language/golang/configure-ci-cd/
|
||||
- /guides/language/golang/configure-ci-cd/
|
||||
- /guides/golang/deploy/
|
||||
- /language/golang/deploy/
|
||||
- /guides/language/golang/deploy/
|
||||
languages: [go]
|
||||
params:
|
||||
time: 30 minutes
|
||||
---
|
||||
|
||||
This guide will show you how to create, test, and deploy containerized Go applications using Docker.
|
||||
|
||||
> **Acknowledgment**
|
||||
>
|
||||
> Docker would like to thank [Oliver Frolovs](https://www.linkedin.com/in/ofr/) for his contribution to this guide.
|
||||
|
||||
## What will you learn?
|
||||
|
||||
In this guide, you’ll learn how to:
|
||||
|
||||
- Create a `Dockerfile` which contains the instructions for building a container image for a program written in Go.
|
||||
- Run the image as a container in your local Docker instance and manage the container's lifecycle.
|
||||
- Use multi-stage builds for building small images efficiently while keeping your Dockerfiles easy to read and maintain.
|
||||
- Use Docker Compose to orchestrate running of multiple related containers together in a development environment.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Some basic understanding of Go and its toolchain is assumed. This isn't a Go tutorial. If you are new to the : languages:,
|
||||
the [Go website](https://golang.org/) is a great place to explore,
|
||||
so _go_ (pun intended) check it out!
|
||||
|
||||
You also must know some basic [Docker concepts](/get-started/docker-concepts/the-basics/what-is-a-container.md) as well as to
|
||||
be at least vaguely familiar with the [Dockerfile format](/manuals/build/concepts/dockerfile.md).
|
||||
|
||||
Your Docker set-up must have BuildKit enabled. BuildKit is enabled by default for all users on [Docker Desktop](/manuals/desktop/_index.md).
|
||||
If you have installed Docker Desktop, you don’t have to manually enable BuildKit. If you are running Docker on Linux,
|
||||
please check out BuildKit [getting started](/manuals/build/buildkit/_index.md#getting-started) page.
|
||||
|
||||
Some familiarity with the command line is also expected.
|
||||
|
||||
## What's next?
|
||||
|
||||
The aim of this guide is to provide enough examples and instructions for you to containerize your own Go application and deploy it into the Cloud.
|
||||
|
||||
Start by building your first Go image.
|
||||
@@ -1,489 +0,0 @@
|
||||
---
|
||||
title: Build your Go image
|
||||
linkTitle: Build images
|
||||
weight: 5
|
||||
keywords: containers, images, go, golang, dockerfiles, coding, build, push, run
|
||||
description: Learn how to build your first Docker image by writing a Dockerfile
|
||||
aliases:
|
||||
- /get-started/golang/build-images/
|
||||
- /language/golang/build-images/
|
||||
- /guides/language/golang/build-images/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In this section you're going to build a container image. The image includes
|
||||
everything you need to run your application – the compiled application binary
|
||||
file, the runtime, the libraries, and all other resources required by your
|
||||
application.
|
||||
|
||||
## Required software
|
||||
|
||||
To complete this tutorial, you need the following:
|
||||
|
||||
- Docker running locally. Follow the [instructions to download and install Docker](/manuals/desktop/_index.md).
|
||||
- An IDE or a text editor to edit files. [Visual Studio Code](https://code.visualstudio.com/) is a free and popular choice but you can use anything you feel comfortable with.
|
||||
- A Git client. This guide uses a command-line based `git` client, but you are free to use whatever works for you.
|
||||
- A command-line terminal application. The examples shown in this module are from the Linux shell, but they should work in PowerShell, Windows Command Prompt, or OS X Terminal with minimal, if any, modifications.
|
||||
|
||||
## Meet the example application
|
||||
|
||||
The example application is a caricature of a microservice. It is purposefully trivial to keep focus on learning the basics of containerization for Go applications.
|
||||
|
||||
The application offers two HTTP endpoints:
|
||||
|
||||
- It responds with a string containing a heart symbol (`<3`) to requests to `/`.
|
||||
- It responds with `{"Status" : "OK"}` JSON to a request to `/health`.
|
||||
|
||||
It responds with HTTP error 404 to any other request.
|
||||
|
||||
The application listens on a TCP port defined by the value of environment variable `PORT`. The default value is `8080`.
|
||||
|
||||
The application is stateless.
|
||||
|
||||
The complete source code for the application is on GitHub: [github.com/docker/docker-gs-ping](https://github.com/docker/docker-gs-ping). You are encouraged to fork it and experiment with it as much as you like.
|
||||
|
||||
To continue, clone the application repository to your local machine:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/docker/docker-gs-ping
|
||||
```
|
||||
|
||||
The application's `main.go` file is straightforward, if you are familiar with Go:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
e := echo.New()
|
||||
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
return c.HTML(http.StatusOK, "Hello, Docker! <3")
|
||||
})
|
||||
|
||||
e.GET("/health", func(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, struct{ Status string }{Status: "OK"})
|
||||
})
|
||||
|
||||
httpPort := os.Getenv("PORT")
|
||||
if httpPort == "" {
|
||||
httpPort = "8080"
|
||||
}
|
||||
|
||||
e.Logger.Fatal(e.Start(":" + httpPort))
|
||||
}
|
||||
|
||||
// Simple implementation of an integer minimum
|
||||
// Adapted from: https://gobyexample.com/testing-and-benchmarking
|
||||
func IntMin(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
```
|
||||
|
||||
## Create a Dockerfile for the application
|
||||
|
||||
To build a container image with Docker, a `Dockerfile` with build instructions is required.
|
||||
|
||||
Begin your `Dockerfile` with the (optional) parser directive line that instructs BuildKit to
|
||||
interpret your file according to the grammar rules for the specified version of the syntax.
|
||||
|
||||
You then tell Docker what base image you would like to use for your application:
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM golang:1.19
|
||||
```
|
||||
|
||||
Docker images can be inherited from other images. Therefore, instead of creating
|
||||
your own base image from scratch, you can use the official Go image that already
|
||||
has all necessary tools and libraries to compile and run a Go application.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you are curious about creating your own base images, you can check out the following section of this guide: [creating base images](/manuals/build/building/base-images.md#create-a-base-image).
|
||||
> Note, however, that this isn't necessary to continue with your task at hand.
|
||||
|
||||
Now that you have defined the base image for your upcoming container image, you
|
||||
can begin building on top of it.
|
||||
|
||||
To make things easier when running the rest of your commands, create a directory
|
||||
inside the image that you're building. This also instructs Docker to use this
|
||||
directory as the default destination for all subsequent commands. This way you
|
||||
don't have to type out full file paths in the `Dockerfile`, the relative paths
|
||||
will be based on this directory.
|
||||
|
||||
```dockerfile
|
||||
WORKDIR /app
|
||||
```
|
||||
|
||||
Usually the very first thing you do once you’ve downloaded a project written in
|
||||
Go is to install the modules necessary to compile it. Note, that the base image
|
||||
has the toolchain already, but your source code isn't in it yet.
|
||||
|
||||
So before you can run `go mod download` inside your image, you need to get your
|
||||
`go.mod` and `go.sum` files copied into it. Use the `COPY` command to do this.
|
||||
|
||||
In its simplest form, the `COPY` command takes two parameters. The first
|
||||
parameter tells Docker what files you want to copy into the image. The last
|
||||
parameter tells Docker where you want that file to be copied to.
|
||||
|
||||
Copy the `go.mod` and `go.sum` file into your project directory `/app` which,
|
||||
owing to your use of `WORKDIR`, is the current directory (`./`) inside the
|
||||
image. Unlike some modern shells that appear to be indifferent to the use of
|
||||
trailing slash (`/`), and can figure out what the user meant (most of the time),
|
||||
Docker's `COPY` command is quite sensitive in its interpretation of the trailing
|
||||
slash.
|
||||
|
||||
```dockerfile
|
||||
COPY go.mod go.sum ./
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> If you'd like to familiarize yourself with the trailing slash treatment by the
|
||||
> `COPY` command, see [Dockerfile
|
||||
> reference](/reference/dockerfile.md#copy). This trailing slash can
|
||||
> cause issues in more ways than you can imagine.
|
||||
|
||||
Now that you have the module files inside the Docker image that you are
|
||||
building, you can use the `RUN` command to run the command `go mod download`
|
||||
there as well. This works exactly the same as if you were running `go` locally
|
||||
on your machine, but this time these Go modules will be installed into a
|
||||
directory inside the image.
|
||||
|
||||
```dockerfile
|
||||
RUN go mod download
|
||||
```
|
||||
|
||||
At this point, you have a Go toolchain version 1.19.x and all your Go
|
||||
dependencies installed inside the image.
|
||||
|
||||
The next thing you need to do is to copy your source code into the image. You’ll
|
||||
use the `COPY` command just like you did with your module files before.
|
||||
|
||||
```dockerfile
|
||||
COPY *.go ./
|
||||
```
|
||||
|
||||
This `COPY` command uses a wildcard to copy all files with `.go` extension
|
||||
located in the current directory on the host (the directory where the `Dockerfile`
|
||||
is located) into the current directory inside the image.
|
||||
|
||||
Now, to compile your application, use the familiar `RUN` command:
|
||||
|
||||
```dockerfile
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping
|
||||
```
|
||||
|
||||
This should be familiar. The result of that command will be a static application
|
||||
binary named `docker-gs-ping` and located in the root of the filesystem of the
|
||||
image that you are building. You could have put the binary into any other place
|
||||
you desire inside that image, the root directory has no special meaning in this
|
||||
regard. It's convenient to use it to keep the file paths short for improved
|
||||
readability.
|
||||
|
||||
Now, all that is left to do is to tell Docker what command to run when your
|
||||
image is used to start a container.
|
||||
|
||||
You do this with the `CMD` command:
|
||||
|
||||
```dockerfile
|
||||
CMD ["/docker-gs-ping"]
|
||||
```
|
||||
|
||||
Here's the complete `Dockerfile`:
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM golang:1.19
|
||||
|
||||
# Set destination for COPY
|
||||
WORKDIR /app
|
||||
|
||||
# Download Go modules
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
# Copy the source code. Note the slash at the end, as explained in
|
||||
# https://docs.docker.com/reference/dockerfile/#copy
|
||||
COPY *.go ./
|
||||
|
||||
# Build
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping
|
||||
|
||||
# Optional:
|
||||
# To bind to a TCP port, runtime parameters must be supplied to the docker command.
|
||||
# But we can document in the Dockerfile what ports
|
||||
# the application is going to listen on by default.
|
||||
# https://docs.docker.com/reference/dockerfile/#expose
|
||||
EXPOSE 8080
|
||||
|
||||
# Run
|
||||
CMD ["/docker-gs-ping"]
|
||||
```
|
||||
|
||||
The `Dockerfile` may also contain comments. They always begin with a `#` symbol,
|
||||
and must be at the beginning of a line. Comments are there for your convenience
|
||||
to allow documenting your `Dockerfile`.
|
||||
|
||||
There is also a concept of Dockerfile directives, such as the `syntax` directive
|
||||
you added. The directives must always be at the very top of the `Dockerfile`, so
|
||||
when adding comments, make sure that the comments follow after any directives
|
||||
that you may have used:
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
# A sample microservice in Go packaged into a container image.
|
||||
|
||||
FROM golang:1.19
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
## Build the image
|
||||
|
||||
Now that you've created your `Dockerfile`, build an image from it. The `docker
|
||||
build` command creates Docker images from the `Dockerfile` and a context. A
|
||||
build context is the set of files located in the specified path or URL. The
|
||||
Docker build process can access any of the files located in the context.
|
||||
|
||||
The build command optionally takes a `--tag` flag. This flag is used to label
|
||||
the image with a string value, which is easy for humans to read and recognize.
|
||||
If you don't pass a `--tag`, Docker will use `latest` as the default value.
|
||||
|
||||
Build your first Docker image.
|
||||
|
||||
```console
|
||||
$ docker build --tag docker-gs-ping .
|
||||
```
|
||||
|
||||
The build process will print some diagnostic messages as it goes through the build steps.
|
||||
The following is an example of what these messages may look like.
|
||||
|
||||
```console
|
||||
[+] Building 2.2s (15/15) FINISHED
|
||||
=> [internal] load build definition from Dockerfile 0.0s
|
||||
=> => transferring dockerfile: 701B 0.0s
|
||||
=> [internal] load .dockerignore 0.0s
|
||||
=> => transferring context: 2B 0.0s
|
||||
=> resolve image config for docker.io/docker/dockerfile:1 1.1s
|
||||
=> CACHED docker-image://docker.io/docker/dockerfile:1@sha256:39b85bbfa7536a5feceb7372a0817649ecb2724562a38360f4d6a7782a409b14 0.0s
|
||||
=> [internal] load build definition from Dockerfile 0.0s
|
||||
=> [internal] load .dockerignore 0.0s
|
||||
=> [internal] load metadata for docker.io/library/golang:1.19 0.7s
|
||||
=> [1/6] FROM docker.io/library/golang:1.19@sha256:5d947843dde82ba1df5ac1b2ebb70b203d106f0423bf5183df3dc96f6bc5a705 0.0s
|
||||
=> [internal] load build context 0.0s
|
||||
=> => transferring context: 6.08kB 0.0s
|
||||
=> CACHED [2/6] WORKDIR /app 0.0s
|
||||
=> CACHED [3/6] COPY go.mod go.sum ./ 0.0s
|
||||
=> CACHED [4/6] RUN go mod download 0.0s
|
||||
=> CACHED [5/6] COPY *.go ./ 0.0s
|
||||
=> CACHED [6/6] RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping 0.0s
|
||||
=> exporting to image 0.0s
|
||||
=> => exporting layers 0.0s
|
||||
=> => writing image sha256:ede8ff889a0d9bc33f7a8da0673763c887a258eb53837dd52445cdca7b7df7e3 0.0s
|
||||
=> => naming to docker.io/library/docker-gs-ping 0.0s
|
||||
```
|
||||
|
||||
Your exact output will vary, but provided there aren't any errors, you should
|
||||
see the word `FINISHED` in the first line of output. This means Docker has
|
||||
successfully built your image named `docker-gs-ping`.
|
||||
|
||||
## View local images
|
||||
|
||||
To see the list of images you have on your local machine, you have two options.
|
||||
One is to use the CLI and the other is to use [Docker
|
||||
Desktop](/manuals/desktop/_index.md). Since you're working in the
|
||||
terminal, take a look at listing images with the CLI.
|
||||
|
||||
To list images, run the `docker image ls`command (or the `docker images` shorthand):
|
||||
|
||||
```console
|
||||
$ docker image ls
|
||||
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
docker-gs-ping latest 7f153fbcc0a8 2 minutes ago 1.11GB
|
||||
...
|
||||
```
|
||||
|
||||
Your exact output may vary, but you should see the `docker-gs-ping` image with
|
||||
the `latest` tag. Because you didn't specify a custom tag when you built your
|
||||
image, Docker assumed that the tag would be `latest`, which is a special value.
|
||||
|
||||
## Tag images
|
||||
|
||||
An image name is made up of slash-separated name components. Name components may
|
||||
contain lowercase letters, digits, and separators. A separator is defined as a
|
||||
period, one or two underscores, or one or more dashes. A name component may not
|
||||
start or end with a separator.
|
||||
|
||||
An image is made up of a manifest and a list of layers. In simple terms, a tag
|
||||
points to a combination of these artifacts. You can have multiple tags for the
|
||||
image and, in fact, most images have multiple tags. Create a second tag
|
||||
for the image you built and take a look at its layers.
|
||||
|
||||
Use the `docker image tag` (or `docker tag` shorthand) command to create a new
|
||||
tag for your image. This command takes two arguments; the first argument is the
|
||||
source image, and the second is the new tag to create. The following command
|
||||
creates a new `docker-gs-ping:v1.0` tag for the `docker-gs-ping:latest` you
|
||||
built:
|
||||
|
||||
```console
|
||||
$ docker image tag docker-gs-ping:latest docker-gs-ping:v1.0
|
||||
```
|
||||
|
||||
The Docker `tag` command creates a new tag for the image. It doesn't create a
|
||||
new image. The tag points to the same image and is another way to reference
|
||||
the image.
|
||||
|
||||
Now run the `docker image ls` command again to see the updated list of local
|
||||
images:
|
||||
|
||||
```console
|
||||
$ docker image ls
|
||||
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
docker-gs-ping latest 7f153fbcc0a8 6 minutes ago 1.11GB
|
||||
docker-gs-ping v1.0 7f153fbcc0a8 6 minutes ago 1.11GB
|
||||
...
|
||||
```
|
||||
|
||||
You can see that you have two images that start with `docker-gs-ping`. You know
|
||||
they're the same image because if you look at the `IMAGE ID` column, you can
|
||||
see that the values are the same for the two images. This value is a unique
|
||||
identifier Docker uses internally to identify the image.
|
||||
|
||||
Remove the tag that you just created. To do this, you’ll use the
|
||||
`docker image rm` command, or the shorthand `docker rmi` (which stands for
|
||||
"remove image"):
|
||||
|
||||
```console
|
||||
$ docker image rm docker-gs-ping:v1.0
|
||||
Untagged: docker-gs-ping:v1.0
|
||||
```
|
||||
|
||||
Notice that the response from Docker tells you that the image hasn't been
|
||||
removed but only untagged.
|
||||
|
||||
Verify this by running the following command:
|
||||
|
||||
```console
|
||||
$ docker image ls
|
||||
```
|
||||
|
||||
You will see that the tag `v1.0` is no longer in the list of images kept by your Docker instance.
|
||||
|
||||
```text
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
docker-gs-ping latest 7f153fbcc0a8 7 minutes ago 1.11GB
|
||||
...
|
||||
```
|
||||
|
||||
The tag `v1.0` has been removed but you still have the `docker-gs-ping:latest`
|
||||
tag available on your machine, so the image is there.
|
||||
|
||||
## Multi-stage builds
|
||||
|
||||
You may have noticed that your `docker-gs-ping` image weighs in at over a
|
||||
gigabyte, which is a lot for a tiny compiled Go application. You may also be
|
||||
wondering what happened to the full suite of Go tools, including the compiler,
|
||||
after you had built your image.
|
||||
|
||||
The answer is that the full toolchain is still there, in the container image.
|
||||
Not only this is inconvenient because of the large file size, but it may also
|
||||
present a security risk when the container is deployed.
|
||||
|
||||
These two issues can be solved by using [multi-stage builds](/manuals/build/building/multi-stage.md).
|
||||
|
||||
In a nutshell, a multi-stage build can carry over the artifacts from one build stage into another,
|
||||
and every build stage can be instantiated from a different base image.
|
||||
|
||||
Thus, in the following example, you are going to use a full-scale official Go
|
||||
image to build your application. Then you'll copy the application binary into
|
||||
another image whose base is very lean and doesn't include the Go toolchain or
|
||||
other optional components.
|
||||
|
||||
The `Dockerfile.multistage` in the sample application's repository has the
|
||||
following content:
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Build the application from source
|
||||
FROM golang:1.19 AS build-stage
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
COPY *.go ./
|
||||
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping
|
||||
|
||||
# Run the tests in the container
|
||||
FROM build-stage AS run-test-stage
|
||||
RUN go test -v ./...
|
||||
|
||||
# Deploy the application binary into a lean image
|
||||
FROM gcr.io/distroless/base-debian11 AS build-release-stage
|
||||
|
||||
WORKDIR /
|
||||
|
||||
COPY --from=build-stage /docker-gs-ping /docker-gs-ping
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
USER nonroot:nonroot
|
||||
|
||||
ENTRYPOINT ["/docker-gs-ping"]
|
||||
```
|
||||
|
||||
Since you have two Dockerfiles now, you have to tell Docker what Dockerfile
|
||||
you'd like to use to build the image. Tag the new image with `multistage`. This
|
||||
tag (like any other, apart from `latest`) has no special meaning for Docker,
|
||||
it's something you chose.
|
||||
|
||||
```console
|
||||
$ docker build -t docker-gs-ping:multistage -f Dockerfile.multistage .
|
||||
```
|
||||
|
||||
Comparing the sizes of `docker-gs-ping:multistage` and `docker-gs-ping:latest`
|
||||
you see a few orders-of-magnitude difference.
|
||||
|
||||
```console
|
||||
$ docker image ls
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
docker-gs-ping multistage e3fdde09f172 About a minute ago 28.1MB
|
||||
docker-gs-ping latest 336a3f164d0f About an hour ago 1.11GB
|
||||
```
|
||||
|
||||
This is so because the ["distroless"](https://github.com/GoogleContainerTools/distroless)
|
||||
base image that you have used in the second stage of the build is very barebones and is designed for lean deployments of static binaries.
|
||||
|
||||
There's much more to multi-stage builds, including the possibility of multi-architecture builds,
|
||||
so feel free to check out [multi-stage builds](/manuals/build/building/multi-stage.md). This is, however, not essential for your progress here.
|
||||
|
||||
## Next steps
|
||||
|
||||
In this module, you met your example application and built and container image
|
||||
for it.
|
||||
|
||||
In the next module, you’ll take a look at how to run your image as a container.
|
||||
@@ -1,733 +0,0 @@
|
||||
---
|
||||
title: Use containers for Go development
|
||||
linkTitle: Develop your app
|
||||
weight: 20
|
||||
keywords: get started, go, golang, local, development
|
||||
description: Learn how to develop your application locally.
|
||||
aliases:
|
||||
- /get-started/golang/develop/
|
||||
- /language/golang/develop/
|
||||
- /guides/language/golang/develop/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Work through the steps of the [run your image as a container](run-containers.md) module to learn how to manage the lifecycle of your containers.
|
||||
|
||||
## Introduction
|
||||
|
||||
In this module, you'll take a look at running a database engine in a container and connecting it to the extended version of the example application. You are going to see some options for keeping persistent data and for wiring up the containers to talk to one another. Finally, you'll learn how to use Docker Compose to manage such multi-container local development environments effectively.
|
||||
|
||||
## Local database and containers
|
||||
|
||||
The database engine you are going to use is called [CockroachDB](https://www.cockroachlabs.com/product/). It is a modern, Cloud-native, distributed SQL database.
|
||||
|
||||
Instead of compiling CockroachDB from the source code or using the operating system's native package manager to install CockroachDB, you are going to use the [Docker image for CockroachDB](https://hub.docker.com/r/cockroachdb/cockroach) and run it in a container.
|
||||
|
||||
CockroachDB is compatible with PostgreSQL to a significant extent, and shares many conventions with the latter, particularly the default names for the environment variables. So, if you are familiar with Postgres, don't be surprised if you see some familiar environment variable names. The Go modules that work with Postgres, such as [pgx](https://pkg.go.dev/github.com/jackc/pgx), [pq](https://pkg.go.dev/github.com/lib/pq), [GORM](https://gorm.io/index.html), and [upper/db](https://upper.io/v4/) also work with CockroachDB.
|
||||
|
||||
For more information on the relation between Go and CockroachDB, refer to the [CockroachDB documentation](https://www.cockroachlabs.com/docs/v20.2/build-a-go-app-with-cockroachdb.html), although this isn't necessary to continue with the present guide.
|
||||
|
||||
### Storage
|
||||
|
||||
The point of a database is to have a persistent store of data. [Volumes](/manuals/engine/storage/volumes.md) are the preferred mechanism for persisting data generated by and used by Docker containers. Thus, before you start CockroachDB, create the volume for it.
|
||||
|
||||
To create a managed volume, run :
|
||||
|
||||
```console
|
||||
$ docker volume create roach
|
||||
roach
|
||||
```
|
||||
|
||||
You can view the list of all managed volumes in your Docker instance with the following command:
|
||||
|
||||
```console
|
||||
$ docker volume list
|
||||
DRIVER VOLUME NAME
|
||||
local roach
|
||||
```
|
||||
|
||||
### Networking
|
||||
|
||||
The example application and the database engine are going to talk to one another over the network. There are different kinds of network configuration possible, and you're going to use what's called a user-defined bridge network. It is going to provide you with a DNS lookup service so that you can refer to your database engine container by its hostname.
|
||||
|
||||
The following command creates a new bridge network named `mynet`:
|
||||
|
||||
```console
|
||||
$ docker network create -d bridge mynet
|
||||
51344edd6430b5acd121822cacc99f8bc39be63dd125a3b3cd517b6485ab7709
|
||||
```
|
||||
|
||||
As it was the case with the managed volumes, there is a command to list all networks set up in your Docker instance:
|
||||
|
||||
```console
|
||||
$ docker network list
|
||||
NETWORK ID NAME DRIVER SCOPE
|
||||
0ac2b1819fa4 bridge bridge local
|
||||
51344edd6430 mynet bridge local
|
||||
daed20bbecce host host local
|
||||
6aee44f40a39 none null local
|
||||
```
|
||||
|
||||
Your bridge network `mynet` has been created successfully. The other three networks, named `bridge`, `host`, and `none` are the default networks and they had been created by the Docker itself. While it's not relevant to this guide, you can learn more about Docker networking in the [networking overview](/manuals/engine/network/_index.md) section.
|
||||
|
||||
### Choose good names for volumes and networks
|
||||
|
||||
As the saying goes, there are only two hard things in Computer Science: cache invalidation and naming things. And off-by-one errors.
|
||||
|
||||
When choosing a name for a network or a managed volume, it's best to choose a name that's indicative of the intended purpose. This guide aims for brevity, so it used short, generic names.
|
||||
|
||||
### Start the database engine
|
||||
|
||||
Now that the housekeeping chores are done, you can run CockroachDB in a container and attach it to the volume and network you had just created. When you run the following command, Docker will pull the image from Docker Hub and run it for you locally:
|
||||
|
||||
```console
|
||||
$ docker run -d \
|
||||
--name roach \
|
||||
--hostname db \
|
||||
--network mynet \
|
||||
-p 26257:26257 \
|
||||
-p 8080:8080 \
|
||||
-v roach:/cockroach/cockroach-data \
|
||||
cockroachdb/cockroach:latest-v25.4 start-single-node \
|
||||
--insecure
|
||||
|
||||
# ... output omitted ...
|
||||
```
|
||||
|
||||
Notice a clever use of the tag `latest-v25.4` to make sure that you're pulling the latest patch version of 25.4. The diversity of available tags depend on the image maintainer. Here, your intent was to have the latest patched version of CockroachDB while not straying too far away from the known working version as the time goes by. To see the tags available for the CockroachDB image, you can go to the [CockroachDB page on Docker Hub](https://hub.docker.com/r/cockroachdb/cockroach/tags).
|
||||
|
||||
### Configure the database engine
|
||||
|
||||
Now that the database engine is live, there is some configuration to do before your application can begin using it. Fortunately, it's not a lot. You must:
|
||||
|
||||
1. Create a blank database.
|
||||
2. Register a new user account with the database engine.
|
||||
3. Grant that new user access rights to the database.
|
||||
|
||||
You can do that with the help of CockroachDB built-in SQL shell. To start the SQL shell in the same container where the database engine is running, type:
|
||||
|
||||
```console
|
||||
$ docker exec -it roach ./cockroach sql --insecure
|
||||
```
|
||||
|
||||
1. In the SQL shell, create the database that the example application is going to use:
|
||||
|
||||
```sql
|
||||
CREATE DATABASE mydb;
|
||||
```
|
||||
|
||||
2. Register a new SQL user account with the database engine. Use the username `totoro`.
|
||||
|
||||
```sql
|
||||
CREATE USER totoro;
|
||||
```
|
||||
|
||||
3. Give the new user the necessary permissions:
|
||||
|
||||
```sql
|
||||
GRANT ALL ON DATABASE mydb TO totoro;
|
||||
```
|
||||
|
||||
4. Type `quit` to exit the shell.
|
||||
|
||||
The following is an example of interaction with the SQL shell.
|
||||
|
||||
```console
|
||||
$ sudo docker exec -it roach ./cockroach sql --insecure
|
||||
#
|
||||
# Welcome to the CockroachDB SQL shell.
|
||||
# All statements must be terminated by a semicolon.
|
||||
# To exit, type: \q.
|
||||
#
|
||||
# Server version: CockroachDB CCL v20.1.15 (x86_64-unknown-linux-gnu, built 2021/04/26 16:11:58, go1.13.9) (same version as client)
|
||||
# Cluster ID: 7f43a490-ccd6-4c2a-9534-21f393ca80ce
|
||||
#
|
||||
# Enter \? for a brief introduction.
|
||||
#
|
||||
root@:26257/defaultdb> CREATE DATABASE mydb;
|
||||
CREATE DATABASE
|
||||
|
||||
Time: 22.985478ms
|
||||
|
||||
root@:26257/defaultdb> CREATE USER totoro;
|
||||
CREATE ROLE
|
||||
|
||||
Time: 13.921659ms
|
||||
|
||||
root@:26257/defaultdb> GRANT ALL ON DATABASE mydb TO totoro;
|
||||
GRANT
|
||||
|
||||
Time: 14.217559ms
|
||||
|
||||
root@:26257/defaultdb> quit
|
||||
oliver@hki:~$
|
||||
```
|
||||
|
||||
### Meet the example application
|
||||
|
||||
Now that you have started and configured the database engine, you can switch your attention to the application.
|
||||
|
||||
The example application for this module is an extended version of `docker-gs-ping` application you've used in the previous modules. You have two options:
|
||||
|
||||
- You can update your local copy of `docker-gs-ping` to match the new extended version presented in this chapter; or
|
||||
- You can clone the [docker/docker-gs-ping-dev](https://github.com/docker/docker-gs-ping-dev) repository. This latter approach is recommended.
|
||||
|
||||
To checkout the example application, run:
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/docker/docker-gs-ping-dev.git
|
||||
# ... output omitted ...
|
||||
```
|
||||
|
||||
The application's `main.go` now includes database initialization code, as well as the code to implement a new business requirement:
|
||||
|
||||
- An HTTP `POST` request to `/send` containing a `{ "value" : string }` JSON must save the value to the database.
|
||||
|
||||
You also have an update for another business requirement. The requirement was:
|
||||
|
||||
- The application responds with a text message containing a heart symbol ("`<3`") on requests to `/`.
|
||||
|
||||
And now it's going to be:
|
||||
|
||||
- The application responds with the string containing the count of messages stored in the database, enclosed in the parentheses.
|
||||
|
||||
Example output: `Hello, Docker! (7)`
|
||||
|
||||
The full source code listing of `main.go` follows.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/cockroachdb/cockroach-go/v2/crdb"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
e := echo.New()
|
||||
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
db, err := initStore()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to initialize the store: %s", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
return rootHandler(db, c)
|
||||
})
|
||||
|
||||
e.GET("/ping", func(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, struct{ Status string }{Status: "OK"})
|
||||
})
|
||||
|
||||
e.POST("/send", func(c echo.Context) error {
|
||||
return sendHandler(db, c)
|
||||
})
|
||||
|
||||
httpPort := os.Getenv("HTTP_PORT")
|
||||
if httpPort == "" {
|
||||
httpPort = "8080"
|
||||
}
|
||||
|
||||
e.Logger.Fatal(e.Start(":" + httpPort))
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func initStore() (*sql.DB, error) {
|
||||
|
||||
pgConnString := fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s sslmode=disable",
|
||||
os.Getenv("PGHOST"),
|
||||
os.Getenv("PGPORT"),
|
||||
os.Getenv("PGDATABASE"),
|
||||
os.Getenv("PGUSER"),
|
||||
os.Getenv("PGPASSWORD"),
|
||||
)
|
||||
|
||||
var (
|
||||
db *sql.DB
|
||||
err error
|
||||
)
|
||||
openDB := func() error {
|
||||
db, err = sql.Open("postgres", pgConnString)
|
||||
return err
|
||||
}
|
||||
|
||||
err = backoff.Retry(openDB, backoff.NewExponentialBackOff())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := db.Exec(
|
||||
"CREATE TABLE IF NOT EXISTS message (value TEXT PRIMARY KEY)"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func rootHandler(db *sql.DB, c echo.Context) error {
|
||||
r, err := countRecords(db)
|
||||
if err != nil {
|
||||
return c.HTML(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return c.HTML(http.StatusOK, fmt.Sprintf("Hello, Docker! (%d)\n", r))
|
||||
}
|
||||
|
||||
func sendHandler(db *sql.DB, c echo.Context) error {
|
||||
|
||||
m := &Message{}
|
||||
|
||||
if err := c.Bind(m); err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
err := crdb.ExecuteTx(context.Background(), db, nil,
|
||||
func(tx *sql.Tx) error {
|
||||
_, err := tx.Exec(
|
||||
"INSERT INTO message (value) VALUES ($1) ON CONFLICT (value) DO UPDATE SET value = excluded.value",
|
||||
m.Value,
|
||||
)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, m)
|
||||
}
|
||||
|
||||
func countRecords(db *sql.DB) (int, error) {
|
||||
|
||||
rows, err := db.Query("SELECT COUNT(*) FROM message")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
count := 0
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&count); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
```
|
||||
|
||||
The repository also includes the `Dockerfile`, which is almost exactly the same as the multi-stage `Dockerfile` introduced in the previous modules. It uses the official Docker Go image to build the application and then builds the final image by placing the compiled binary into the much slimmer, distroless image.
|
||||
|
||||
Regardless of whether you had updated the old example application, or checked out the new one, this new Docker image has to be built to reflect the changes to the application source code.
|
||||
|
||||
### Build the application
|
||||
|
||||
You can build the image with the familiar `build` command:
|
||||
|
||||
```console
|
||||
$ docker build --tag docker-gs-ping-roach .
|
||||
```
|
||||
|
||||
### Run the application
|
||||
|
||||
Now, run your container. This time you'll need to set some environment variables so that your application knows how to access the database. For now, you’ll do this right in the `docker run` command. Later you'll see a more convenient method with Docker Compose.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Since you're running your CockroachDB cluster in insecure mode, the value for the password can be anything.
|
||||
>
|
||||
> In production, don't run in insecure mode.
|
||||
|
||||
```console
|
||||
$ docker run -it --rm -d \
|
||||
--network mynet \
|
||||
--name rest-server \
|
||||
-p 80:8080 \
|
||||
-e PGUSER=totoro \
|
||||
-e PGPASSWORD=myfriend \
|
||||
-e PGHOST=db \
|
||||
-e PGPORT=26257 \
|
||||
-e PGDATABASE=mydb \
|
||||
docker-gs-ping-roach
|
||||
```
|
||||
|
||||
There are a few points to note about this command.
|
||||
|
||||
- You map container port `8080` to host port `80` this time. Thus, for `GET` requests you can get away with literally `curl localhost`:
|
||||
|
||||
```console
|
||||
$ curl localhost
|
||||
Hello, Docker! (0)
|
||||
```
|
||||
|
||||
Or, if you prefer, a proper URL would work just as well:
|
||||
|
||||
```console
|
||||
$ curl http://localhost/
|
||||
Hello, Docker! (0)
|
||||
```
|
||||
|
||||
- The total number of stored messages is `0` for now. This is fine, because you haven't posted anything to your application yet.
|
||||
- You refer to the database container by its hostname, which is `db`. This is why you had `--hostname db` when you started the database container.
|
||||
|
||||
- The actual password doesn't matter, but it must be set to something to avoid confusing the example application.
|
||||
- The container you've just run is named `rest-server`. These names are useful for managing the container lifecycle:
|
||||
|
||||
```console
|
||||
# Don't do this just yet, it's only an example:
|
||||
$ docker container rm --force rest-server
|
||||
```
|
||||
|
||||
### Test the application
|
||||
|
||||
In the previous section, you've already tested querying your application with `GET` and it returned zero for the stored message counter. Now, post some messages to it:
|
||||
|
||||
```console
|
||||
$ curl --request POST \
|
||||
--url http://localhost/send \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{"value": "Hello, Docker!"}'
|
||||
```
|
||||
|
||||
The application responds with the contents of the message, which means it has been saved in the database:
|
||||
|
||||
```json
|
||||
{ "value": "Hello, Docker!" }
|
||||
```
|
||||
|
||||
Send another message:
|
||||
|
||||
```console
|
||||
$ curl --request POST \
|
||||
--url http://localhost/send \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{"value": "Hello, Oliver!"}'
|
||||
```
|
||||
|
||||
And again, you get the value of the message back:
|
||||
|
||||
```json
|
||||
{ "value": "Hello, Oliver!" }
|
||||
```
|
||||
|
||||
Run curl and see what the message counter says:
|
||||
|
||||
```console
|
||||
$ curl localhost
|
||||
Hello, Docker! (2)
|
||||
```
|
||||
|
||||
In this example, you sent two messages and the database kept them. Or has it? Stop and remove all your containers, but not the volumes, and try again.
|
||||
|
||||
First, stop the containers:
|
||||
|
||||
```console
|
||||
$ docker container stop rest-server roach
|
||||
rest-server
|
||||
roach
|
||||
```
|
||||
|
||||
Then, remove them:
|
||||
|
||||
```console
|
||||
$ docker container rm rest-server roach
|
||||
rest-server
|
||||
roach
|
||||
```
|
||||
|
||||
Verify that they're gone:
|
||||
|
||||
```console
|
||||
$ docker container list --all
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
```
|
||||
|
||||
And start them again, database first:
|
||||
|
||||
```console
|
||||
$ docker run -d \
|
||||
--name roach \
|
||||
--hostname db \
|
||||
--network mynet \
|
||||
-p 26257:26257 \
|
||||
-p 8080:8080 \
|
||||
-v roach:/cockroach/cockroach-data \
|
||||
cockroachdb/cockroach:latest-v25.4 start-single-node \
|
||||
--insecure
|
||||
```
|
||||
|
||||
And the service next:
|
||||
|
||||
```console
|
||||
$ docker run -it --rm -d \
|
||||
--network mynet \
|
||||
--name rest-server \
|
||||
-p 80:8080 \
|
||||
-e PGUSER=totoro \
|
||||
-e PGPASSWORD=myfriend \
|
||||
-e PGHOST=db \
|
||||
-e PGPORT=26257 \
|
||||
-e PGDATABASE=mydb \
|
||||
docker-gs-ping-roach
|
||||
```
|
||||
|
||||
Lastly, query your service:
|
||||
|
||||
```console
|
||||
$ curl localhost
|
||||
Hello, Docker! (2)
|
||||
```
|
||||
|
||||
Great! The count of records from the database is correct although you haven't only stopped the containers, but you've also removed them before starting new instances. The difference is in the managed volume for CockroachDB, which you reused. The new CockroachDB container has read the database files from the disk, just as it normally would if it were running outside the container.
|
||||
|
||||
### Wind down everything
|
||||
|
||||
Remember, that you're running CockroachDB in insecure mode. Now that you've built and tested your application, it's time to wind everything down before moving on. You can list the containers that you are running with the `list` command:
|
||||
|
||||
```console
|
||||
$ docker container list
|
||||
```
|
||||
|
||||
Now that you know the container IDs, you can use `docker container stop` and `docker container rm`, as demonstrated in the previous modules.
|
||||
|
||||
Stop the CockroachDB and `docker-gs-ping-roach` containers before moving on.
|
||||
|
||||
## Better productivity with Docker Compose
|
||||
|
||||
At this point, you might be wondering if there is a way to avoid having to deal with long lists of arguments to the `docker` command. The toy example you used in this series requires five environment variables to define the connection to the database. A real application might need many, many more. Then there is also a question of dependencies. Ideally, you want to make sure that the database is started before your application is run. And spinning up the database instance may require another Docker command with many options. But there is a better way to orchestrate these deployments for local development purposes.
|
||||
|
||||
In this section, you'll create a Docker Compose file to start your `docker-gs-ping-roach` application and CockroachDB database engine with a single command.
|
||||
|
||||
### Configure Docker Compose
|
||||
|
||||
In your application's directory, create a new text file named `compose.yaml` with the following content.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
docker-gs-ping-roach:
|
||||
depends_on:
|
||||
- roach
|
||||
build:
|
||||
context: .
|
||||
container_name: rest-server
|
||||
hostname: rest-server
|
||||
networks:
|
||||
- mynet
|
||||
ports:
|
||||
- 80:8080
|
||||
environment:
|
||||
- PGUSER=${PGUSER:-totoro}
|
||||
- PGPASSWORD=${PGPASSWORD:?database password not set}
|
||||
- PGHOST=${PGHOST:-db}
|
||||
- PGPORT=${PGPORT:-26257}
|
||||
- PGDATABASE=${PGDATABASE:-mydb}
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
roach:
|
||||
image: cockroachdb/cockroach:latest-v25.4
|
||||
container_name: roach
|
||||
hostname: db
|
||||
networks:
|
||||
- mynet
|
||||
ports:
|
||||
- 26257:26257
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- roach:/cockroach/cockroach-data
|
||||
command: start-single-node --insecure
|
||||
|
||||
volumes:
|
||||
roach:
|
||||
|
||||
networks:
|
||||
mynet:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
This Docker Compose configuration is super convenient as you don't have to type all the parameters to pass to the `docker run` command. You can declaratively do that in the Docker Compose file. The [Docker Compose documentation pages](/manuals/compose/_index.md) are quite extensive and include a full reference for the Docker Compose file format.
|
||||
|
||||
### The `.env` file
|
||||
|
||||
Docker Compose will automatically read environment variables from a `.env` file if it's available. Since your Compose file requires `PGPASSWORD` to be set, add the following content to the `.env` file:
|
||||
|
||||
```bash
|
||||
PGPASSWORD=whatever
|
||||
```
|
||||
|
||||
The exact value doesn't really matter for this example, because you run CockroachDB in insecure mode. Make sure you set the variable to some value to avoid getting an error.
|
||||
|
||||
### Merging Compose files
|
||||
|
||||
The filename `compose.yaml` is the default filename which `docker compose` command recognizes if no `-f` flag is provided. This means you can have multiple Docker Compose files if your environment has such requirements. Furthermore, Docker Compose files are composable, so multiple files can be specified on the command line to merge parts of the configuration together. The following list shows a few examples of scenarios where such a feature would be useful:
|
||||
|
||||
- Using a bind mount for the source code for local development but not when running the CI tests;
|
||||
- Switching between using a pre-built image for the frontend for some API application vs creating a bind mount for source code;
|
||||
- Adding additional services for integration testing;
|
||||
- And many more...
|
||||
|
||||
You aren't going to cover any of these advanced use cases here.
|
||||
|
||||
### Variable substitution in Docker Compose
|
||||
|
||||
One of the really cool features of Docker Compose is [variable substitution](/reference/compose-file/interpolation.md). You can see some examples in the Compose file, `environment` section. By means of an example:
|
||||
|
||||
- `PGUSER=${PGUSER:-totoro}` means that inside the container, the environment variable `PGUSER` shall be set to the same value as it has on the host machine where Docker Compose is run. If there is no environment variable with this name on the host machine, the variable inside the container gets the default value of `totoro`.
|
||||
- `PGPASSWORD=${PGPASSWORD:?database password not set}` means that if the environment variable `PGPASSWORD` isn't set on the host, Docker Compose will display an error. This is OK, because you don't want to hard-code default values for the password. You set the password value in the `.env` file, which is local to your machine. It is always a good idea to add `.env` to `.gitignore` to prevent the secrets being checked into the version control.
|
||||
|
||||
Other ways of dealing with undefined or empty values exist, as documented in the [variable substitution](/reference/compose-file/interpolation.md) section of the Docker documentation.
|
||||
|
||||
### Validating Docker Compose configuration
|
||||
|
||||
Before you apply changes made to a Compose configuration file, there is an opportunity to validate the content of the configuration file with the following command:
|
||||
|
||||
```console
|
||||
$ docker compose config
|
||||
```
|
||||
|
||||
When this command is run, Docker Compose reads the file `compose.yaml`, parses it into a data structure in memory, validates where possible, and prints back the reconstruction of that configuration file from its internal representation. If this isn't possible due to errors, Docker prints an error message instead.
|
||||
|
||||
### Build and run the application using Docker Compose
|
||||
|
||||
Start your application and confirm that it's running.
|
||||
|
||||
```console
|
||||
$ docker compose up --build
|
||||
```
|
||||
|
||||
You passed the `--build` flag so Docker will compile your image and then start it.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Docker Compose is a useful tool, but it has its own quirks. For example, no rebuild is triggered on the update to the source code unless the `--build` flag is provided. It is a very common pitfall to edit one's source code, and forget to use the `--build` flag when running `docker compose up`.
|
||||
|
||||
Since your set-up is now run by Docker Compose, it has assigned it a project name, so you get a new volume for your CockroachDB instance. This means that your application will fail to connect to the database, because the database doesn't exist in this new volume. The terminal displays an authentication error for the database:
|
||||
|
||||
```text
|
||||
# ... omitted output ...
|
||||
rest-server | 2021/05/10 00:54:25 failed to initialise the store: pq: password authentication failed for user totoro
|
||||
roach | *
|
||||
roach | * INFO: Replication was disabled for this cluster.
|
||||
roach | * When/if adding nodes in the future, update zone configurations to increase the replication factor.
|
||||
roach | *
|
||||
roach | CockroachDB node starting at 2021-05-10 00:54:26.398177 +0000 UTC (took 3.0s)
|
||||
roach | build: CCL v20.1.15 @ 2021/04/26 16:11:58 (go1.13.9)
|
||||
roach | webui: http://db:8080
|
||||
roach | sql: postgresql://root@db:26257?sslmode=disable
|
||||
roach | RPC client flags: /cockroach/cockroach <client cmd> --host=db:26257 --insecure
|
||||
roach | logs: /cockroach/cockroach-data/logs
|
||||
roach | temp dir: /cockroach/cockroach-data/cockroach-temp349434348
|
||||
roach | external I/O path: /cockroach/cockroach-data/extern
|
||||
roach | store[0]: path=/cockroach/cockroach-data
|
||||
roach | storage engine: rocksdb
|
||||
roach | status: initialized new cluster
|
||||
roach | clusterID: b7b1cb93-558f-4058-b77e-8a4ddb329a88
|
||||
roach | nodeID: 1
|
||||
rest-server exited with code 0
|
||||
rest-server | 2021/05/10 00:54:25 failed to initialise the store: pq: password authentication failed for user totoro
|
||||
rest-server | 2021/05/10 00:54:26 failed to initialise the store: pq: password authentication failed for user totoro
|
||||
rest-server | 2021/05/10 00:54:29 failed to initialise the store: pq: password authentication failed for user totoro
|
||||
rest-server | 2021/05/10 00:54:25 failed to initialise the store: pq: password authentication failed for user totoro
|
||||
rest-server | 2021/05/10 00:54:26 failed to initialise the store: pq: password authentication failed for user totoro
|
||||
rest-server | 2021/05/10 00:54:29 failed to initialise the store: pq: password authentication failed for user totoro
|
||||
rest-server exited with code 1
|
||||
# ... omitted output ...
|
||||
```
|
||||
|
||||
Because of the way you set up your deployment using `restart_policy`, the failing container is being restarted every 20 seconds. So, in order to fix the problem, you need to log in to the database engine and create the user. You've done it before in [Configure the database engine](#configure-the-database-engine).
|
||||
|
||||
This isn't a big deal. All you have to do is to connect to CockroachDB instance and run the three SQL commands to create the database and the user, as described in [Configure the database engine](#configure-the-database-engine).
|
||||
|
||||
So, log in to the database engine from another terminal:
|
||||
|
||||
```console
|
||||
$ docker exec -it roach ./cockroach sql --insecure
|
||||
```
|
||||
|
||||
And run the same commands as before to create the database `mydb`, the user `totoro`, and to grant that user necessary permissions. Once you do that (and the example application container is automatically restarts), the `rest-service` stops failing and restarting and the console goes quiet.
|
||||
|
||||
It would have been possible to connect the volume that you had previously used, but for the purposes of this example it's more trouble than it's worth and it also provided an opportunity to show how to introduce resilience into your deployment via the `restart_policy` Compose file feature.
|
||||
|
||||
### Testing the application
|
||||
|
||||
Now, test your API endpoint. In the new terminal, run the following command:
|
||||
|
||||
```console
|
||||
$ curl http://localhost/
|
||||
```
|
||||
|
||||
You should receive the following response:
|
||||
|
||||
```json
|
||||
Hello, Docker! (0)
|
||||
```
|
||||
|
||||
### Shutting down
|
||||
|
||||
To stop the containers started by Docker Compose, press `ctrl+c` in the terminal where you ran `docker compose up`. To remove those containers after they've been stopped, run `docker compose down`.
|
||||
|
||||
### Detached mode
|
||||
|
||||
You can run containers started by the `docker compose` command in detached mode, just as you would with the `docker` command, by using the `-d` flag.
|
||||
|
||||
To start the stack, defined by the Compose file in detached mode, run:
|
||||
|
||||
```console
|
||||
$ docker compose up --build -d
|
||||
```
|
||||
|
||||
Then, you can use `docker compose stop` to stop the containers and `docker compose down` to remove them.
|
||||
|
||||
## Further exploration
|
||||
|
||||
You can run `docker compose` to see what other commands are available.
|
||||
|
||||
## Wrap up
|
||||
|
||||
There are some tangential, yet interesting points that were purposefully not covered in this chapter. For the more adventurous reader, this section offers some pointers for further study.
|
||||
|
||||
### Persistent storage
|
||||
|
||||
A managed volume isn't the only way to provide your container with persistent storage. It is highly recommended to get acquainted with available storage options and their use cases, covered in [Manage data in Docker](/manuals/engine/storage/_index.md).
|
||||
|
||||
### CockroachDB clusters
|
||||
|
||||
You ran a single instance of CockroachDB, which was enough for this example. But, it's possible to run a CockroachDB cluster, which is made of multiple instances of CockroachDB, each instance running in its own container. Since CockroachDB engine is distributed by design, it would have taken surprisingly little change to your procedure to run a cluster with multiple nodes.
|
||||
|
||||
Such distributed set-up offers interesting possibilities, such as applying Chaos Engineering techniques to simulate parts of the cluster failing and evaluating your application's ability to cope with such failures.
|
||||
|
||||
If you are interested in experimenting with CockroachDB clusters, check out:
|
||||
|
||||
- [Start a CockroachDB Cluster in Docker](https://www.cockroachlabs.com/docs/v20.2/start-a-local-cluster-in-docker-mac.html) article; and
|
||||
- Documentation for Docker Compose keywords [`deploy`](/reference/compose-file/legacy-versions.md) and [`replicas`](/reference/compose-file/legacy-versions.md).
|
||||
|
||||
### Other databases
|
||||
|
||||
Since you didn't run a cluster of CockroachDB instances, you might be wondering whether you could have used a non-distributed database engine. The answer is 'yes', and if you were to pick a more traditional SQL database, such as [PostgreSQL](https://www.postgresql.org/), the process described in this chapter would have been very similar.
|
||||
|
||||
## Next steps
|
||||
|
||||
In this module, you set up a containerized development environment with your application and the database engine running in different containers. You also wrote a Docker Compose file which links the two containers together and provides for easy starting up and tearing down of the development environment.
|
||||
|
||||
In the next module, you'll take a look at one possible approach to running functional tests in Docker.
|
||||
1536
content/guides/golang/index.md
Normal file
1536
content/guides/golang/index.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,210 +0,0 @@
|
||||
---
|
||||
title: Run your Go image as a container
|
||||
linkTitle: Run containers
|
||||
weight: 10
|
||||
keywords: get started, go, golang, run, container
|
||||
description: Learn how to run the image as a container.
|
||||
aliases:
|
||||
- /get-started/golang/run-containers/
|
||||
- /language/golang/run-containers/
|
||||
- /guides/language/golang/run-containers/
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Work through the steps to containerize a Go application in [Build your Go image](build-images.md).
|
||||
|
||||
## Overview
|
||||
|
||||
In the previous module you created a `Dockerfile` for your example application and then you created your Docker image using the command `docker build`. Now that you have the image, you can run that image and see if your application is running correctly.
|
||||
|
||||
A container is a normal operating system process except that this process is isolated and has its own file system, its own networking, and its own isolated process tree separate from the host.
|
||||
|
||||
To run an image inside of a container, you use the `docker run` command. It requires one parameter and that's the image name. Start your image and make sure it's running correctly. Run the following command in your terminal.
|
||||
|
||||
```console
|
||||
$ docker run docker-gs-ping
|
||||
```
|
||||
|
||||
```text
|
||||
____ __
|
||||
/ __/___/ / ___
|
||||
/ _// __/ _ \/ _ \
|
||||
/___/\__/_//_/\___/ v4.10.2
|
||||
High performance, minimalist Go web framework
|
||||
https://echo.labstack.com
|
||||
____________________________________O/_______
|
||||
O\
|
||||
⇨ http server started on [::]:8080
|
||||
```
|
||||
|
||||
When you run this command, you’ll notice that you weren't returned to the command prompt. This is because your application is a REST server and will run in a loop waiting for incoming requests without returning control back to the OS until you stop the container.
|
||||
|
||||
Make a GET request to the server using the curl command.
|
||||
|
||||
```console
|
||||
$ curl http://localhost:8080/
|
||||
curl: (7) Failed to connect to localhost port 8080: Connection refused
|
||||
```
|
||||
|
||||
Your curl command failed because the connection to your server was refused.
|
||||
Meaning that you weren't able to connect to localhost on port 8080. This is
|
||||
expected because your container is running in isolation which includes
|
||||
networking. Stop the container and restart with port 8080 published on your
|
||||
local network.
|
||||
|
||||
To stop the container, press ctrl-c. This will return you to the terminal prompt.
|
||||
|
||||
To publish a port for your container, you’ll use the `--publish` flag (`-p` for short) on the `docker run` command. The format of the `--publish` command is `[host_port]:[container_port]`. So if you wanted to expose port `8080` inside the container to port `3000` outside the container, you would pass `3000:8080` to the `--publish` flag.
|
||||
|
||||
Start the container and expose port `8080` to port `8080` on the host.
|
||||
|
||||
```console
|
||||
$ docker run --publish 8080:8080 docker-gs-ping
|
||||
```
|
||||
|
||||
Now, rerun the curl command.
|
||||
|
||||
```console
|
||||
$ curl http://localhost:8080/
|
||||
Hello, Docker! <3
|
||||
```
|
||||
|
||||
Success! You were able to connect to the application running inside of your container on port 8080. Switch back to the terminal where your container is running and you should see the `GET` request logged to the console.
|
||||
|
||||
Press `ctrl-c` to stop the container.
|
||||
|
||||
## Run in detached mode
|
||||
|
||||
This is great so far, but your sample application is a web server and you
|
||||
shouldn't have to have your terminal connected to the container. Docker can run
|
||||
your container in detached mode in the background. To do this, you can use the
|
||||
`--detach` or `-d` for short. Docker will start your container the same as
|
||||
before but this time will detach from the container and return you to the
|
||||
terminal prompt.
|
||||
|
||||
```console
|
||||
$ docker run -d -p 8080:8080 docker-gs-ping
|
||||
d75e61fcad1e0c0eca69a3f767be6ba28a66625ce4dc42201a8a323e8313c14e
|
||||
```
|
||||
|
||||
Docker started your container in the background and printed the container ID on the terminal.
|
||||
|
||||
Again, make sure that your container is running. Run the same `curl` command:
|
||||
|
||||
```console
|
||||
$ curl http://localhost:8080/
|
||||
Hello, Docker! <3
|
||||
```
|
||||
|
||||
## List containers
|
||||
|
||||
Since you ran your container in the background, how do you know if your container is running or what other containers are running on your machine? Well, to see a list of containers running on your machine, run `docker ps`. This is similar to how the ps command is used to see a list of processes on a Linux machine.
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
|
||||
```
|
||||
|
||||
The `ps` command tells you a bunch of stuff about your running containers. You can see the container ID, the image running inside the container, the command that was used to start the container, when it was created, the status, ports that are exposed, and the names of the container.
|
||||
|
||||
You are probably wondering where the name of your container is coming from. Since you didn’t provide a name for the container when you started it, Docker generated a random name. You'll fix this in a minute but first you need to stop the container. To stop the container, run the `docker stop` command, passing the container's name or ID.
|
||||
|
||||
```console
|
||||
$ docker stop inspiring_ishizaka
|
||||
inspiring_ishizaka
|
||||
```
|
||||
|
||||
Now rerun the `docker ps` command to see a list of running containers.
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
```
|
||||
|
||||
## Stop, start, and name containers
|
||||
|
||||
Docker containers can be started, stopped and restarted. When you stop a container, it's not removed but the status is changed to stopped and the process inside of the container is stopped. When you ran the `docker ps` command, the default output is to only show running containers. If you pass the `--all` or `-a` for short, you will see all containers on your system, including stopped containers and running containers.
|
||||
|
||||
```console
|
||||
$ docker ps --all
|
||||
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
d75e61fcad1e docker-gs-ping "/docker-gs-ping" About a minute ago Exited (2) 23 seconds ago inspiring_ishizaka
|
||||
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 2 minutes ago wizardly_joliot
|
||||
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 3 minutes ago magical_carson
|
||||
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 9 minutes ago Exited (2) 3 minutes ago gifted_mestorf
|
||||
```
|
||||
|
||||
If you’ve been following along, you should see several containers listed. These are containers that you started and stopped but haven't removed yet.
|
||||
|
||||
Restart the container that you have just stopped. Locate the name of the container and replace the name of the container in the following `restart` command:
|
||||
|
||||
```console
|
||||
$ docker restart inspiring_ishizaka
|
||||
```
|
||||
|
||||
Now, list all the containers again using the `ps` command:
|
||||
|
||||
```console
|
||||
$ docker ps -a
|
||||
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 2 minutes ago Up 5 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
|
||||
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 2 minutes ago wizardly_joliot
|
||||
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 4 minutes ago magical_carson
|
||||
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 10 minutes ago Exited (2) 4 minutes ago gifted_mestorf
|
||||
```
|
||||
|
||||
Notice that the container you just restarted has been started in detached mode and has port `8080` exposed. Also, note that the status of the container is `Up X seconds`. When you restart a container, it will be started with the same flags or commands that it was originally started with.
|
||||
|
||||
Stop and remove all of your containers and take a look at fixing the random naming issue.
|
||||
|
||||
Stop the container you just started. Find the name of your running container and replace the name in the following command with the name of the container on your system:
|
||||
|
||||
```console
|
||||
$ docker stop inspiring_ishizaka
|
||||
inspiring_ishizaka
|
||||
```
|
||||
|
||||
Now that all of your containers are stopped, remove them. When a container is removed, it's no longer running nor is it in the stopped state. Instead, the process inside the container is terminated and the metadata for the container is removed.
|
||||
|
||||
To remove a container, run the `docker rm` command passing the container name. You can pass multiple container names to the command in one command.
|
||||
|
||||
Again, make sure you replace the containers names in the following command with the container names from your system:
|
||||
|
||||
```console
|
||||
$ docker rm inspiring_ishizaka wizardly_joliot magical_carson gifted_mestorf
|
||||
|
||||
inspiring_ishizaka
|
||||
wizardly_joliot
|
||||
magical_carson
|
||||
gifted_mestorf
|
||||
```
|
||||
|
||||
Run the `docker ps --all` command again to verify that all containers are gone.
|
||||
|
||||
Now, address the pesky random name issue. Standard practice is to name your containers for the simple reason that it's easier to identify what's running in the container and what application or service it's associated with. Just like good naming conventions for variables in your code makes it simpler to read. So goes naming your containers.
|
||||
|
||||
To name a container, you must pass the `--name` flag to the `run` command:
|
||||
|
||||
```console
|
||||
$ docker run -d -p 8080:8080 --name rest-server docker-gs-ping
|
||||
3bbc6a3102ea368c8b966e1878a5ea9b1fc61187afaac1276c41db22e4b7f48f
|
||||
```
|
||||
|
||||
```console
|
||||
$ docker ps
|
||||
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
3bbc6a3102ea docker-gs-ping "/docker-gs-ping" 25 seconds ago Up 24 seconds 0.0.0.0:8080->8080/tcp rest-server
|
||||
```
|
||||
|
||||
Now, you can easily identify your container based on the name.
|
||||
|
||||
## Next steps
|
||||
|
||||
In this module, you learned how to run containers and publish ports. You also learned to manage the lifecycle of containers. You then learned the importance of naming your containers so that they're more easily identifiable. In the next module, you’ll learn how to run a database in a container and connect it to your application.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user