How to Use Testcontainers on Jenkins CI

Releasing software often and with confidence relies on a strong continuous integration and continuous delivery (CI/CD) process that includes the ability to automate tests. Jenkins offers an open source automation server that facilitates such release of software projects.

In this article, we will explore how you can run tests based on the open source Testcontainers framework in a Jenkins pipeline using Docker and Testcontainers Cloud. 

Jenkins, which streamlines the development process by automating the building, testing, and deployment of code changes, is widely adopted in the DevOps ecosystem. It supports a vast array of plugins, enabling integration with various tools and technologies, making it highly customizable to meet specific project requirements.

Testcontainers is an open source framework for provisioning throwaway, on-demand containers for development and testing use cases. Testcontainers makes it easy to work with databases, message brokers, web browsers, or just about anything that can run in a Docker container.

Testcontainers also provides support for many popular programming languages, including Java, Go, .NET, Node.js, Python, and more. This article will show how to test a Java Spring Boot application (testcontainers-showcase) using Testcontainers in a Jenkins pipeline. Please fork the repository into your GitHub account. To run Testcontainers-based tests, a Testcontainers-supported container runtime, like Docker, needs to be available to agents.

Note: As Jenkins CI servers are mostly run on Linux machines, the following configurations are tested on a Linux machine only.

Docker containers as Jenkins agents

Let’s see how to use dynamic Docker container-based agents. To be able to use Docker containers as agents, install the Docker Pipeline plugin. 

Now, let’s create a file with name Jenkinsfile in the root of the project with the following content:

pipeline {
agent {
docker {
image 'eclipse-temurin:17.0.9_9-jdk-jammy'
args '–network host -u root -v /var/run/docker.sock:/var/run/docker.sock'
}
}

triggers { pollSCM 'H/2 * * * *' } // poll every 2 mins

stages {
stage('Build and Test') {
steps {
sh './mvnw verify'
}
}
}
}

We are using the eclipse-temurin:17.0.9_9-jdk-jammy Docker container as an agent to run the builds for this pipeline. Note that we are mapping the host’s Unix Docker socket as a volume with root user permissions to make it accessible to the agent, but this can potentially be a security risk.

Add the Jenkinsfile and push the changes to the Git repository.

Now, go to the Jenkins Dashboard and select New Item to create the pipeline. Follow these steps:

Enter testcontainers-showcase as pipeline name.

Select Pipeline as job type.

Select OK.

Under Pipeline section:

Select Definition: Pipeline script from SCM.

SCM: Git.

Repository URL: https://github.com/YOUR_GITHUB_USERNAME/testcontainers-showcase.git. Replace YOUR_GITHUB_USERNAME with your actual GitHub username.

Branches to build: Branch Specifier (blank for ‘any’): */main.

Script Path: Jenkinsfile.

Select Save.

Choose Build Now to trigger the pipeline for the first time.

The pipeline should run the Testcontainers-based tests successfully in a container-based agent using the remote Docker-in-Docker based configuration.

Kubernetes pods as Jenkins agents

While running Testcontainers-based tests on Kubernetes pods, you can run a Docker-in-Docker (DinD) container as a sidecar. To use Kubernetes pods as Jenkins agents, install Kubernetes plugin.

Now you can create the Jenkins pipeline using Kubernetes pods as agents as follows:

def pod =
"""
apiVersion: v1
kind: Pod
metadata:
labels:
name: worker
spec:
serviceAccountName: jenkins
containers:
– name: java17
image: eclipse-temurin:17.0.9_9-jdk-jammy
resources:
requests:
cpu: "1000m"
memory: "2048Mi"
imagePullPolicy: Always
tty: true
command: ["cat"]
– name: dind
image: docker:dind
imagePullPolicy: Always
tty: true
env:
– name: DOCKER_TLS_CERTDIR
value: ""
securityContext:
privileged: true
"""

pipeline {
agent {
kubernetes {
yaml pod
}
}
environment {
DOCKER_HOST = 'tcp://localhost:2375'
DOCKER_TLS_VERIFY = 0
}

stages {
stage('Build and Test') {
steps {
container('java17') {
script {
sh "./mvnw verify"
}
}
}
}
}
}

Although we can use a Docker-in-Docker based configuration to make the Docker environment available to the agent, this setup also brings configuration complexities and security risks.

By volume mounting the host’s Docker Unix socket (Docker-out-of-Docker) with the agents, the agents have direct access to the host Docker engine.

When using DooD approach file sharing, using bind-mounting doesn’t work because the containerized app and Docker engine work in different contexts. 

The Docker-in-Docker (DinD) approach requires the use of insecure privileged containers.

You can watch the Docker-in-Docker: Containerized CI Workflows presentation to learn more about the challenges of a Docker-in-Docker based CI setup.

This is where Testcontainers Cloud comes into the picture to make it easy to run Testcontainers-based tests more simply and reliably. 

By using Testcontainers Cloud, you don’t even need a Docker daemon running on the agent. Containers will be run in on-demand cloud environments so that you don’t need to use powerful CI agents with high CPU/memory for your builds.

Let’s see how to use Testcontainers Cloud with minimal setup and run Testcontainers-based tests.

Testcontainers Cloud-based setup

Testcontainers Cloud helps you run Testcontainers-based tests at scale by spinning up the dependent services as Docker containers on the cloud and having your tests connect to those services.

If you don’t have a Testcontainers Cloud account already, you can create an account and get a Service Account Token as follows:

Sign up for a Testcontainers Cloud account.

Once logged in, create an organization.

Navigate to the Testcontainers Cloud dashboard and generate a Service account (Figure 1).

Figure 1: Create a new Testcontainers Cloud service account.

To use Testcontainers Cloud, we need to start a lightweight testcontainers-cloud agent by passing TC_CLOUD_TOKEN as an environment variable.

You can store the TC_CLOUD_TOKEN value as a secret in Jenkins as follows:

From the Dashboard, select Manage Jenkins.

Under Security, choose Credentials.

You can create a new domain or use System domain.

Under Global credentials, select Add credentials.

Select Kind as Secret text.

Enter TC_CLOUD_TOKEN value in Secret.

Enter tc-cloud-token-secret-id as ID.

Select Create.

Next, you can update the Jenkinsfile as follows:

pipeline {
agent {
docker {
image 'eclipse-temurin:17.0.9_9-jdk-jammy'
}
}

triggers { pollSCM 'H/2 * * * *' }

stages {

stage('TCC SetUp') {
environment {
TC_CLOUD_TOKEN = credentials('tc-cloud-token-secret-id')
}
steps {
sh "curl -fsSL https://get.testcontainers.cloud/bash | sh"
}
}

stage('Build and Test') {
steps {
sh './mvnw verify'
}
}
}
}

We have set the TC_CLOUD_TOKEN environment variable using the value from tc-cloud-token-secret-id credential we created and started a Testcontainers Cloud agent before running our tests.

Now if you commit and push the updated Jenkinsfile, then the pipeline will run the tests using Testcontainers Cloud. You should see log statements similar to the following indicating that the Testcontainers-based tests are using Testcontainers Cloud instead of the default Docker daemon.

14:45:25.748 [testcontainers-lifecycle-0] INFO org.testcontainers.DockerClientFactory – Connected to docker:
Server Version: 78+testcontainerscloud (via Testcontainers Desktop 1.5.5)
API Version: 1.43
Operating System: Ubuntu 20.04 LTS
Total Memory: 7407 MB

You can also leverage Testcontainers Cloud’s Turbo mode in conjunction with build tools that feature parallel run capabilities to run tests even faster.

In the case of Maven, you can use the -DforkCount=N system property to specify the degree of parallelization. For Gradle, you can specify the degree of parallelization using the maxParallelForks property.

We can enable parallel execution of our tests using four forks in Jenkinsfile as follows:

stage('Build and Test') {
steps {
sh './mvnw verify -DforkCount=4'
}
}

For more information, check out the article on parallelizing your tests with Turbo mode.

Conclusion

In this article, we have explored how to run Testcontainers-based tests on Jenkins CI using dynamic containers and Kubernetes pods as agents with Docker-out-of-Docker and Docker-in-Docker based configuration. 

Then we learned how to create a Testcontainers Cloud account and configure the pipeline to run tests using Testcontainers Cloud. We also explored leveraging Testcontainers Cloud Turbo mode combined with your build tool’s parallel execution capabilities. 

Although we have demonstrated this setup using a Java project as an example, Testcontainers libraries exist for other popular languages, too, and you can follow the same pattern of configuration to run your Testcontainers-based tests on Jenkins CI in Golang, .NET, Python, Node.js, etc.

Get started with Testcontainers Cloud by creating a free account at the website.

Learn more

Sign up for a Testcontainers Cloud account.

Watch the Docker-in-Docker: Containerized CI Workflows session from DockerCon 2023.

Subscribe to the Docker Newsletter.

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

How to Use OpenPubkey to Solve Key Management via SSO

This post was contributed by BastionZero.

Giving people the ability to sign messages under their identity is extremely powerful. For instance, this functionality lets you SSH into servers, sign software artifacts, and create end-to-end encrypted communications under your single sign-on (SSO) identity.

The OpenPubkey protocol and open source project brings the power of digital signatures to both people and workloads without adding trusted parties. OpenPubkey is built on the OpenID Connect (OIDC) SSO protocol, which is supported by major identity providers, including Google, Microsoft, Okta, and Facebook. 

This article will explore how OpenPubkey works and look at three use cases in detail.

What can OpenPubkey do?

Public key cryptography was invented in the 1970s and has become the most powerful tool in the security engineering toolbox. It allows anything holding a public key, and its associated signing key, to create a cryptographic identity. This identity is extremely secure because the party cannot only use their signing key to prove they are who they say they are but also sign messages under this identity. 

Servers often authenticate themselves to people using public keys associated with the server’s identity, yet the process rarely works the other way. People rarely authenticate to servers using public keys associated with a person’s identity. Instead, less secure authentication methods are employed, such as authentication secrets stored in cookies, which must be transmitted on every request.Let’s say that Alice wanted to sign the message “Flee at once — all is discovered” under her email address alice@example.com. How would she do it? One approach would be for Alice to create a public key (PK) and signing key (SK) and then publish the mapping between her email and the PK. 

This approach has two problems. First, you and everyone verifying this message must trust that the webpage has honestly mapped Alice’s email to her public key and has not maliciously replaced her public key with another key that could be used to impersonate Alice. Second, Alice must now protect and manage the signing key associated with this public key. History has shown that users can be terrible at protecting signing keys. Probably the most famous example is of the man who lost a signing key controlling half a billion dollars worth of Bitcoin.Human authentication on the web was originally supposed to work the same way as server authentication. Much like a certificate authority (CA) issues a certificate to a server, which associates a public key with the server’s identity (`example.com`), the plan was to have a CA issue a client certificate to a person that associates a public key with that person’s identity. These client certificates are still around and are well-used for certain applications, but they never caught on for widespread personal use, likely because of the terrible user experience (UX) of asking people to secure and manage secret signing keys.OpenPubkey addresses both of these problems. It uses your identity provider to perform the mapping between identity and your public key. Because you already trust your identity provider, having your identity provider perform this mapping does not add any new trusted parties. For instance, Alice must already trust her identity provider, Example.com, to manage her identity (alice@example.com), so it is natural to use Example.com to perform the mapping between Alice’s public key and her Example.com identity (alice@example.com). Example.com already knows how to authenticate @example.com users, so Alice doesn’t need to set up a new account or create new authentication factors.Second, to solve the problem of lost or stolen signing keys, OpenPubkey public keys and signing keys are ephemeral. That means the signing keys can be deleted and recreated at will. OpenPubkey generates a fresh public key and signing key for a user every time that user authenticates to their identity provider. This approach to making public keys ephemeral removes one of the most significant UX barriers to authenticating people with public keys. It also provides a security win; it creates a much smaller window of exposure if a signing key is stolen, as signing keys can be deleted when the user idles or logs out.

How does OpenPubkey work?

Let’s return to our situation: Alice wants to sign the message “Flee at once — all is discovered” under her identity (alice@example.com). First, Alice’s computer generates a fresh public key and signing key. Next, she needs her identity provider, Example.com, to associate her identity with this public key. How does OpenPubkey do this? To understand the process, we first need to provide details about how SSO/OpenID Connect works.Example.com, which is the identity provider for @example.com, knows how to check that Alice is really alice@example.com. Example.com does this every time Alice signs into Example.com. In OIDC, the identity provider signs a statement, called an ID Token, which roughly says “this is alice@example.com”. Part of the authentication process in OIDC allows the user (or their software) to submit a random value that will be included in the issued ID Token. 

Alice’s OpenPubkey client puts the cryptographic hash of Alice’s public key into this value in her ID Token. Alice’s OpenPubkey client modifies the ID Token into an object called a PK Token, which essentially says: “this is alice@example.com and her public key is 0xABCE…“. We’re skipping a few details of OpenPubkey, but this is the basic idea.

Now that Alice has a PK Token signed by Example.com, which binds her public key to her identity, she can sign the statement “Flee at once — all is discovered” and broadcast the message, the signature, and her ID Token. Bob, or anyone else for that matter, can check whether this message is really from alice@example.com, by checking that the ID Token is signed by Example.com and then checking that Alice’s signature matches the public key in the ID Token.

OpenPubkey use cases

Now let’s look at OpenPubkey use cases.

SSH

OpenPubkey is useful for more than just telling your friends that “Flee at once — all is discovered.” Because most security protocols are built on public key cryptography, OpenPubkey can easily plug human identities into these protocols.

SSH supports the authentication of both machines and users with public keys (also known as SSH keys).  However, these SSH keys are not associated with identities. With an SSH key, you can say “allow root access for key 0xABCD…”, but not “allow root access for alice@example.com.” This presents several UX and security problems. As mentioned previously, people struggle with managing their secret signing keys, and SSH is no exception. 

Even more problematic, because public keys are not associated with identities, it is difficult to tell if an SSH key represents a person or machine that should no longer have access. As Tatu Ylonen, the inventor of SSH, writes in his recent paper Challenges in Managing SSH Keys — and a Call for Solutions:

“In analyzing SSH keys for dozens of large enterprises, it has turned out that in many environments 90% of all authorized keys are no longer used. They represent access that was provisioned, but never terminated when the person left or the need for access ceased to exist. Some of the authorized keys are 10-20 years old, and typically about 10% of them grant root access or other privileged access. The vast majority of private user keys found in most environments do not have passphrases.”

OpenPubkey can be used to solve this problem by binding SSH keys to user identities. That way,  the server can check whether the identity (alice@example.com) is allowed to connect to the server or not. This means that Alice can access her SSH server using SSO; she can log in to Example.com as alice@example.com and then gain access to the server as long as her SSO is valid.OpenPubkey authentication can be added to SSH with a small change to the SSH config. No code changes to SSH are required. To try it out, or learn more about how OpenPubkey’s SSH works, see our recent post: How to Use OpenPubkey to SSH Without SSH Keys.

Secure messaging

OpenPubkey can also be used to solve one of the major issues with end-to-end encrypted messaging. Suppose someone sends you a message on a secure messaging app: How do you know they are actually that person? Some secure messaging apps let you look up the public key that is securing your communication, but how do you know that that public key is actually the public key of the person you want to privately communicate with?This connection between public key and identity is the core problem that OpenPubkey solves. With OpenPubkey, Bob can learn the public key for alice@example.com by checking an ID Token signed by Example.com, which includes Alice’s public key and her email address. This does involve trusting Example.com, but you generally already have to trust Example.com to SSO @example.com users.

While it’s not discussed here, OpenPubkey does support an optional protocol — the MFA cosigner — which removes the requirement of trusting the identity provider. But even without the MFA cosigner protocol, OpenPubkey provides stronger security for end-to-end encrypted messaging because it allows Bob to learn Alice’s public key directly from Alice’s identity provider.

Signing container images

OpenPubkey is not limited to human use cases. OpenPubkey developers are working on a solution to allow workflows (rather than people) to sign images using GitHub’s identity provider and GitHub Actions. You can learn more about this use case by reading How to Use OpenPubkey with GitHub Actions Workloads.

Help us expand the utility of OpenPubkey

These three use cases should not be seen as the limits of what OpenPubkey can do. This approach is highly flexible and can be used for VPNs, cosigning, container service meshes, cryptocurrencies, web applications, and even physical access. 

We invite anyone who wants to contribute to OpenPubkey to visit and star our GitHub repo. We are building an open and friendly community and welcome pull requests from anyone — see the contribution guidelines to learn more.    

Learn more

Read How to Use OpenPubkey with GitHub Actions Workloads.

Read How to use OpenPubkey to SSH Without SSH Keys.

Fireside chat — Redefining Security Standards: Identity Providers as Certificate Authorities.

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Docker Desktop 4.27: Synchronized File Shares, Docker Init GA, Private Extensions Marketplace, Moby 25, Support for Testcontainers with ECI, Docker Build Cloud, and Docker Debug Beta

We’re pleased to announce Docker Desktop 4.27, packed with exciting new features and updates. The new release includes key advancements such as synchronized file shares, collaboration enhancements in Docker Build Cloud, the introduction of the private marketplace for extensions (available for Docker Business customers), and the much-anticipated release of Moby 25. 

Additionally, we explore the support for Testcontainers with Enhanced Container Isolation, the general availability of docker init with expanded language support, and the beta release of Docker Debug. These updates represent significant strides in improving development workflows, enhancing security, and offering advanced customization for Docker users.

Docker Desktop synchronized file shares GA

We’re diving into some fantastic updates for Docker Desktop, and we’re especially thrilled to introduce our latest feature, synchronized file shares, which is available now in version 4.27 (Figure 1). Following our acquisition announcement in June 2023, we have integrated the technology behind Mutagen into the core of Docker Desktop.

You can now say goodbye to the challenges of using large codebases in containers with virtual filesystems. Synchronized file shares unlock native filesystem performance for bind mounts and provides a remarkable 2-10x boost in file operation speeds. For developers managing extensive codebases, this is a game-changer.

Figure 1: Shares have been created and are available for use in containers.

To get started, log in to Docker Desktop with your subscription account (Pro, Teams, or Business) to harness the power of Docker Desktop synchronized file shares. You can read more about this feature in the Docker documentation.

Collaborate on shared Docker Build Cloud builds in Docker Desktop

With the recent GA of Docker Build Cloud, your team can now leverage Docker Desktop to use powerful cloud-based build machines and shared caching to reduce unnecessary rebuilds and get your build done in a fraction of the time, regardless of your local physical hardware.

New builds can make instant use of the shared cache. Even if this is your first time building the project, you can immediately speed up build times with shared caches.

We know that team members have varying levels of Docker expertise. When a new developer has issues with their build failing, the Builds view makes it effortless for anyone on the team to locate the troublesome build using search and filtering. They can then collaborate on a fix and get unblocked in no time.

When all your team is building on the same cloud builder, it can get noisy, so we added filtering by specific build types, helping you focus on the builds that are important to you.

Link to builder settings for a build

Previously, to access builder settings, you had to jump back to the build list or the settings page, but now you can access them directly from a build (Figure 2).

Figure 2: Access builder settings directly from a build.

Delete build history for a builder

And, until now you could only delete build in batches, which meant if you wanted to clear the build history it required a lot of clicks. This update enables you to clear all builds easily (Figure 3).

Figure 3: Painlessly clear the build history for an individual builder.

Refresh storage data for your builder at any point in time

Refreshing the storage data is an intensive operation, so it only happens periodically. Previously, when you were clearing data, you would have to wait a while to see the update. Now it’s just a one-click process (Figure 4).

Figure 4: Quickly refresh storage data for a builder to get an up-to-date view of your usage.

New feature: Private marketplace for extensions available for Docker Business subscribers

Docker Business customers now have exclusive access to a new feature: the private marketplace for extensions. This enhancement focuses on security, compliance, and customization, and empowering developers, providing:

Controlled access: Manage which extensions developers can use through allow-listing.

Private distribution: Easily distribute company-specific extensions from a private registry.

Customized development: Deploy customized team processes and tools as unpublished/private Docker extensions tailored to a specific organization.

The private marketplace for extensions enables a secure, efficient, and tailored development environment, aligning with your enterprise’s specific needs. Get started today by learning how to configure a private marketplace for extensions.

Moby 25 release — containerd image store 

We are happy to announce the release of Moby 25.0 with Docker Desktop 4.27. In case you’re unfamiliar, Moby is the open source project for Docker Engine, which ships in Docker Desktop. We have dedicated significant effort to this release, which marks a major release milestone for the open source Moby project. You can read a comprehensive list of enhancements in the v25.0.0 release notes.

With the release of Docker Desktop 4.27,  support for the containerd image store has graduated from beta to general availability. This work began in September 2022 when we started extending the Docker Engine integration with containerd, so we are excited to have this functionality reach general availability.

This support provides a more robust user experience by natively storing and building multi-platform images and using snapshotters for lazy pulling images (e.g., stargz) and peer-to-peer image distribution (e.g., dragonfly, nydus). It also provides a foundation for you to run Wasm containers (currently in beta). 

Using the containerd image store is not currently enabled by default for all users but can be enabled in the general settings in Docker Desktop under Use containers for pulling and storing images (Figure 5).

Figure 5: Enable use of the containerd image store in the general settings in Docker Desktop.

Going forward, we will continue improving the user experience of pushing, pulling, and storing images with the containerd image store, help migrate user images to use containerd, and work toward enabling it by default for all users. 

As always, you can try any of the features landing in Moby 25 in Docker Desktop.

Support for Testcontainers with Enhanced Container Isolation

Docker Desktop 4.27 introduces the ability to use the popular Testcontainers framework with Enhanced Container Isolation (ECI). 

ECI, which is available to Docker Business customers, provides an additional layer of security to prevent malicious workloads running in containers from compromising the Docker Desktop or the host by running containers without root access to the Docker Desktop VM, by vetting sensitive system calls inside containers and other advanced techniques. It’s meant to better secure local development environments. 

Before Docker Desktop 4.27, ECI blocked mounting the Docker Engine socket into containers to increase security and prevent malicious containers from gaining access to Docker Engine. However, this also prevented legitimate scenarios (such as Testcontainers) from working with ECI.   

Starting with Docker Desktop 4.27, admins can now configure ECI to allow Docker socket mounts, but in a controlled way (e.g., on trusted images of their choice) and even restrict the commands that may be sent on that socket. This functionality, in turn, enables users to enjoy the combined benefits of frameworks such as Testcontainers (or any others that require containers to access the Docker engine socket) with the extra security and peace of mind provided by ECI.

Docker init GA with Java support 

Initially released in its beta form in Docker 4.18, docker init has undergone several enhancements. The docker init command-line utility aids in the initialization of Docker resources within a project. It automatically generates Dockerfiles, Compose files, and .dockerignore files based on the nature of the project, significantly reducing the setup time and complexity associated with Docker configurations. 

The initial beta release of docker init only supported Go and generic projects. The latest version, available in Docker 4.27, supports Go, Python, Node.js, Rust, ASP.NET, PHP, and Java (Figure 6).

Figure 6. Docker init will suggest the best template for the application.

The general availability of docker init offers an efficient and user-friendly way to integrate Docker into your projects. Whether you’re a seasoned Docker user or new to containerization, docker init is ready to enhance your development workflow. 

Beta release of Docker Debug 

As previously announced at DockerCon 2023, Docker Debug is now available as a beta offering in Docker Desktop 4.27.

Figure 7: Docker Debug.

Developers can spend as much as 60% of their time debugging their applications, with much of that time taken up by sorting and configuring tools and setup instead of debugging. Docker Debug (available in Pro, Teams, or Business subscriptions) provides a language-independent, integrated toolbox for debugging local and remote containerized apps — even when the container fails to launch — enabling developers to find and solve problems faster.

To get started, run docker debug <Container or Image name> in the Docker Desktop CLI while logged in with your subscription account.

Conclusion

Docker Desktop’s latest updates and features, from synchronized file shares to the first beta release of Docker Debug, reflect our ongoing commitment to enhancing developer productivity and operational efficiency. Integrating these capabilities into Docker Desktop streamlines development processes and empowers teams to collaborate more effectively and securely. As Docker continues to evolve, we remain dedicated to providing our community and customers with innovative solutions that address the dynamic needs of modern software development.Stay tuned for further updates and enhancements, and as always, we encourage you to explore these new features to see how they can benefit your development workflow.Upgrade to Docker Desktop 4.27 to explore these updates and experiment with Docker’s latest features.

Learn more

Read the Docker Desktop Release Notes.

Install and authenticate against the latest release of Docker Desktop.

Learn more about synchronized file shares.

Check out Docker Build Cloud.

Read Streamline Dockerization with Docker Init GA

Read Docker Init: Initialize Dockerfiles and Compose files with a single CLI command.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Build Multimodal GenAI Apps with OctoAI and Docker

This post was contributed by Thierry Moreau, co-founder and head of DevRel at OctoAI.

Generative AI models have shown immense potential over the past year with breakthrough models like GPT3.5, DALL-E, and more. In particular, open source foundational models have gained traction among developers and enterprise users who appreciate how customizable, cost-effective, and transparent these models are compared to closed-source alternatives.

In this article, we’ll explore how you can compose an open source foundational model into a streamlined image transformation pipeline that lets you manipulate images with nothing but text to achieve surprisingly good results.

With this approach, you can create fun versions of corporate logos, bring your kids’ drawings to life, enrich your product photography, or even remodel your living room (Figure 1).

Figure 1: Examples of image transformation including, from left to right: Generating creative corporate logo, bringing children’s drawings to life, enriching commercial photography, remodeling your living room

Pretty cool, right? Behind the scenes, a lot needs to happen, and we’ll walk step by step through how to reproduce these results yourself. We call the multimodal GenAI pipeline OctoShop as a nod to the popular image editing software.

Feeling inspired to string together some foundational GenAI models? Let’s dive into the technology that makes this possible.

Architecture overview

Let’s look more closely at the open source foundational GenAI models that compose the multimodal pipeline we’re about to build.

Going forward, we’ll use the term “model cocktail” instead of “multimodal GenAI model pipeline,” as it flows a bit better (and sounds tastier, too). A model cocktail is a mix of GenAI models that can process and generate data across multiple modalities: text and images are examples of data modalities across which GenAI models consume and produce data, but the concept can also extend to audio and video (Figure 2).

To build on the analogy of crafting a cocktail (or mocktail, if you prefer), you’ll need to mix ingredients, which, when assembled, are greater than the sum of their individual parts.

Figure 2: The multimodal GenAI workflow — by taking an image and text, this pipeline transforms the input image according to the text prompt.

Let’s use a Negroni, for example — my favorite cocktail. It’s easy to prepare; you need equal parts of gin, vermouth, and Campari. Similarly, our OctoShop model cocktail will use three ingredients: an equal mix of image-generation (SDXL), text-generation (Mistral-7B), and a custom image-to-text generation (CLIP Interrogator) model. 

The process is as follows: 

CLIP Interrogator takes in an image and generates a textual description (e.g., “a whale with a container on its back”).

An LLM model, Mistral-7B, will generate a richer textual description based on a user prompt (e.g., “set the image into space”). The LLM will consequently transform the description into a richer one that meets the user prompt (e.g., “in the vast expanse of space, a majestic whale carries a container on its back”).

Finally, an SDXL model will be used to generate a final AI-generated image based on the textual description transformed by the LLM model. We also take advantage of SDXL styles and a ControlNet to better control the output of the image in terms of style and framing/perspective.

Prerequisites

Let’s go over the prerequisites for crafting our cocktail.

Here’s what you’ll need:

Sign up for an OctoAI account to use OctoAI’s image generation (SDXL), text generation (Mistral-7B), and compute solutions (CLIP Interrogator) — OctoAI serves as the bar from which to get all of the ingredients you’ll need to craft your model cocktail. If you’re already using a different compute service, feel free to bring that instead.

Run a Jupyter notebook to craft the right mix of GenAI models. This is your place for experimenting and mixing, so this will be your cocktail shaker. To make it easy to run and distribute the notebook, we’ll use Google Colab.

Finally, we’ll deploy our model cocktail as a Streamlit app. Think of building your app and embellishing the frontend as the presentation of your cocktail (e.g., glass, ice, and choice of garnish) to enhance your senses.

Getting started with OctoAI

Head to octoai.cloud and create an account if you haven’t done so already. You’ll receive $10 in credits upon signing up for the first time, which should be sufficient for you to experiment with your own workflow here.

Follow the instructions on the Getting Started page to obtain an OctoAI API token — this will help you get authenticated whenever you use the OctoAI APIs. 

Notebook walkthrough

We’ve built a Jupyter notebook in Colab to help you learn how to use the different models that will constitute your model cocktail. Here are the steps to follow: 

1. Launch the notebook

Get started by launching the following Colab notebook. 

There’s no need to change the runtime type or rely on a GPU or TPU accelerator — all we need is a CPU here, given that all of the AI heavy-lifting is done on OctoAI endpoints.

2. OctoAI SDK setup

Let’s get started by installing the OctoAI SDK. You’ll use the SDK to invoke the different open source foundational models we’re using, like SDXL and Mistral-7B. You can install through pip:

# Install the OctoAI SDK
!pip install octoai-sdk

In some cases, you may get a message about pip packages being previously imported in the runtime, causing an error. If that’s the case, selecting the Restart Session button at the bottom should take care of the package versioning issues. After this, you should be able to re-run the cell that pip-installs the OctoAI SDK without any issues.

3. Generate images with SDXL

You’ll first learn to generate an image with SDXL using the Image Generation solution API. To learn more about what each parameter does in the code below, check out OctoAI’s ImageGenerator client.

In particular, the ImageGenerator API takes several arguments to generate an image:

Engine: Lets you choose between versions of Stable Diffusion models, such as SDXL, SD1.5, and SSD.

Prompt: Describes the image you want to generate.

Negative prompt: Describes the traits you want to avoid in the final image.

Width, height: The resolution of the output image.

Num images: The number of images to generate at once.

Sampler: Determines the sampling method used to denoise your image. If you’re not familiar with this process, this article provides a comprehensive overview.

Number of steps: Number of denoising steps — the more steps, the higher the quality, but generally going past 30 will lead to diminishing returns.

Cfg scale: How closely to adhere to the image description — generally stays around 7-12.

Use refiner: Whether to apply the SDXL refiner model, which improves the output quality of the image.

Seed: A parameter that lets you control the reproducibility of image generation (set to a positive value to always get the same image given stable input parameters).

Note that tweaking the image generation parameters — like number of steps, number of images, sampler used, etc. — affects the amount of GPU compute needed to generate an image. Increasing GPU cycles will affect the pricing of generating the image. 

Here’s an example using simple parameters:

# To use OctoAI, we'll need to set up OctoAI to use it
from octoai.clients.image_gen import Engine, ImageGenerator

# Now let's use the OctoAI Image Generation API to generate
# an image of a whale with a container on its back to recreate
# the moby logo
image_gen = ImageGenerator(token=OCTOAI_API_TOKEN)
image_gen_response = image_gen.generate(
engine=Engine.SDXL,
prompt="a whale with a container on its back",
negative_prompt="blurry photo, distortion, low-res, poor quality",
width=1024,
height=1024,
num_images=1,
sampler="DPM_PLUS_PLUS_2M_KARRAS",
steps=20,
cfg_scale=7.5,
use_refiner=True,
seed=1
)
images = image_gen_response.images

# Display generated image from OctoAI
for i, image in enumerate(images):
pil_image = image.to_pil()
display(pil_image)

Feel free to experiment with the parameters to see what happens to the resulting image. In this case, I’ve put in a simple prompt meant to describe the Docker logo: “a whale with a container on its back.” I also added standard negative prompts to help generate the style of image I’m looking for. Figure 3 shows the output:

Figure 3: An SDXL-generated image of a whale with a container on its back.

4. Control your image output with ControlNet

One thing you may want to do with SDXL is control the composition of your AI-generated image. For example, you can specify a specific human pose or control the composition and perspective of a given photograph, etc. 

For our experiment using Moby (the Docker mascot), we’d like to get an AI-generated image that can be easily superimposed onto the original logo — same shape of whale and container, orientation of the subject, size, and so forth. 

This is where ControlNet can come in handy: they let you constrain the generation of images by feeding a control image as input. In our example we’ll feed the image of the Moby logo as our control input.

By tweaking the following parameters used by the ImageGenerator API, we are constraining the SDXL image generation with a control image of Moby. That control image will be converted into a depth map using a depth estimation model, then fed into the ControlNet, which will constrain SDXL image generation.

# Set the engine to controlnet SDXL
engine="controlnet-sdxl",
# Select depth controlnet which uses a depth map to apply
# constraints to SDXL
controlnet="depth_sdxl",
# Set the conditioning scale anywhere between 0 and 1, try different
# values to see what they do!
controlnet_conditioning_scale=0.3,
# Pass in the base64 encoded string of the moby logo image
controlnet_image=image_to_base64(moby_image),

Now the result looks like it matches the Moby outline a lot more closely (Figure 4). This is the power of ControlNet. You can adjust the strength by varying the controlnet_conditioning_scale parameter. This way, you can make the output image more or less faithfully match the control image of Moby.

Figure 4: Left: The Moby logo is used as a control image to a ControlNet. Right: the SDXL-generated image resembles the control image more closely than in the previous example.

5. Control your image output with SDXL style presets

Let’s add a layer of customization with SDXL styles. We’ll use the 3D Model style preset (Figure 5). Behind the scenes, these style presets are adding additional keywords to the positive and negative prompts that the SDXL model ingests.

Figure 5: You can try various styles on the OctoAI Image Generation solution UI — there are more than 100 to choose from, each delivering a unique feel and aesthetic.

Figure 6 shows how setting this one parameter in the ImageGenerator API transforms our AI-generated image of Moby. Go ahead and try out more styles; we’ve generated a gallery for you to get inspiration from.

Figure 6: SDXL-generated image of Moby with the “3D Model” style preset applied.

6. Manipulate images with Mistral-7B LLM

So far we’ve relied on SDXL, which does text-to-image generation. We’ve added ControlNet in the mix to apply a control image as a compositional constraint. 

Next, we’re going to layer an LLM into the mix to transform our original image prompt into a creative and rich textual description based on a “transformation prompt.” 

Basically, we’re going to use an LLM to make our prompt better automatically. This will allow us to perform image manipulation using text in our OctoShop model cocktail pipeline:

Take a logo of Moby: Set it into an ultra-realistic photo in space.

Take a child’s drawing: Bring it to life in a fantasy world.

Take a photo of a cocktail: Set it on a beach in Italy.

Take a photo of a living room: Transform it into a staged living room in a designer house.

To achieve this text-to-text transformation, we will use the LLM user prompt as follows. This sets the original textual description of Moby into a new setting: the vast expanse of space.

'''
Human: set the image description into space: “a whale with a container on its back”
AI: '''

We’ve configured the LLM system prompt so that LLM responses are concise and at most one sentence long. We could make them longer, but be aware that the prompt consumed by SDXL has a 77-token context limit.

You can read more on the text generation Python SDK and its Chat Completions API used to generate text:

Model: Lets you choose out of selection of foundational open source models like Mixtral, Mistral, Llama2, Code Llama (the selection will grow with more open source models being released).

Messages: Contains a list of messages (system and user) to use as context for the completion.

Max tokens: Enforces a hard limit on output tokens (this could cut a completion response in the middle of a sentence).

Temperature: Lets you control the creativity of your answer: with a higher temperature, less likely tokens can be selected.

The choice of model, input, and output tokens will influence pricing on OctoAI. In this example, we’re using the Mistral-7B LLM, which is a great open source LLM model that really packs a punch given its small parameter size. 

Let’s look at the code used to invoke our Mistral-7B LLM:

# Let's go ahead and start with the original prompt that we used in our
# image generation examples.
image_desc = "a whale with a container on its back"

# Let's then prepare our LLM prompt to manipulate our image
llm_prompt = '''
Human: set the image description into space: {}
AI: '''.format(image_desc)

# Now let's use an LLM to transform this craft clay rendition
# of Moby into a fun scify universe
from octoai.client import Client

client = Client(OCTOAI_API_TOKEN)
completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "You are a helpful assistant. Keep your responses short and limited to one sentence."
},
{
"role": "user",
"content": llm_prompt
}
],
model="mistral-7b-instruct-fp16",
max_tokens=128,
temperature=0.01
)

# Print the message we get back from the LLM
llm_image_desc = completion.choices[0].message.content
print(llm_image_desc)

Here’s the output:

Our LLM has created a short yet imaginative description of Moby traveling through space. Figure 7 shows the result when we feed this LLM-generated textual description into SDXL.

Figure 7: SDXL-generated image of Moby where we used an LLM to set the scene in space and enrich the text prompt.

This image is great. We can feel the immensity of space. With the power of LLMs and the flexibility of SDXL, we can take image creation and manipulation to new heights. And the great thing is, all we need to manipulate those images is text; the GenAI models do the rest of the work.

7. Automate the workflow with AI-based image labeling

So far in our image transformation pipeline, we’ve had to manually label the input image to our OctoShop model cocktail. Instead of just passing in the image of Moby, we had to provide a textual description of that image.

Thankfully, we can rely on a GenAI model to perform text labeling tasks: CLIP Interrogator. Think of this task as the reverse of what SDXL does: It takes in an image and produces text as the output.

To get started, we’ll need a CLIP Interrogator model running behind an endpoint somewhere. There are two ways to get a CLIP Interrogator model endpoint on OctoAI. If you’re just getting started, we recommend the simple approach, and if you feel inspired to customize your model endpoint, you can use the more advanced approach. For instance, you may be interested in trying out the more recent version of CLIP Interrogator.

You can now invoke the CLIP Interrogator model in a few lines of code. We’ll use the fast interrogator mode here to get a label generated as quickly as possible.

# Let's go ahead and invoke the CLIP interrogator model

# Note that under a cold start scenario, you may need to wait a minute or two
# to get the result of this inference… Be patient!
output = client.infer(
endpoint_url=CLIP_ENDPOINT_URL+'/predict',
inputs={
"image": image_to_base64(moby_image),
"mode": "fast"
}
)

# All labels
clip_labels = output["completion"]["labels"]
print(clip_labels)

# Let's get just the top label
top_label = clip_labels.split(',')[0]
print(top_label)

The top label described our Moby logo as:

That’s pretty on point. Now that we’ve tested all ingredients individually, let’s assemble our model cocktail and test it on interesting use cases.

8. Assembling the model cocktail

Now that we have tested our three models (CLIP interrogator, Mistral-7B, SDXL), we can package them into one convenient function, which takes the following inputs:

An input image that will be used to control the output image and also be automatically labeled by our CLIP interrogator model.

A transformation string that describes the transformation we want to apply to the input image (e.g., “set the image description in space”).

A style string which lets us better control the artistic output of the image independently of the transformation we apply to it (e.g., painterly style vs. cinematic).

The function below is a rehash of all of the code we’ve introduced above, packed into one function.

def genai_transform(image: Image, transformation: str, style: str) -> Image:
# Step 1: CLIP captioning
output = client.infer(
endpoint_url=CLIP_ENDPOINT_URL+'/predict',
inputs={
"image": image_to_base64(image),
"mode": "fast"
}
)
clip_labels = output["completion"]["labels"]
top_label = clip_labels.split(',')[0]

# Step 2: LLM transformation
llm_prompt = '''
Human: {}: {}
AI: '''.format(transformation, top_label)
completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": "You are a helpful assistant. Keep your responses short and limited to one sentence."
},
{
"role": "user",
"content": llm_prompt
}
],
model="mistral-7b-instruct-fp16",
max_tokens=128,
presence_penalty=0,
temperature=0.1,
top_p=0.9,
)
llm_image_desc = completion.choices[0].message.content

# Step 3: SDXL+controlnet transformation
image_gen_response = image_gen.generate(
engine="controlnet-sdxl",
controlnet="depth_sdxl",
controlnet_conditioning_scale=0.4,
controlnet_image=image_to_base64(image),
prompt=llm_image_desc,
negative_prompt="blurry photo, distortion, low-res, poor quality",
width=1024,
height=1024,
num_images=1,
sampler="DPM_PLUS_PLUS_2M_KARRAS",
steps=20,
cfg_scale=7.5,
use_refiner=True,
seed=1,
style_preset=style
)
images = image_gen_response.images

# Display generated image from OctoAI
pil_image = images[0].to_pil()
return top_label, llm_image_desc, pil_image

Now you can try this out on several images, prompts, and styles. 

Package your model cocktail into a web app

Now that you’ve mixed your unique GenAI cocktail, it’s time to pour it into a glass and garnish it, figuratively speaking. We built a simple Streamlit frontend that lets you deploy your unique OctoShop GenAI model cocktail and share the results with your friends and colleagues (Figure 8). You can check it on GitHub.

Follow the README instructions to deploy your app locally or get it hosted on Streamlit’s web hosting services.

Figure 8: The Streamlit app transforms images into realistic renderings in space — all thanks to the magic of GenAI.

We look forward to seeing what great image-processing apps you come up with. Go ahead and share your creations on OctoAI’s Discord server in the #built_with_octo channel! 

If you want to learn how you can put OctoShop behind a Discord Bot or build your own model containers with Docker, we also have instructions on how to do that from an AI/ML workshop organized by OctoAI at DockerCon 2023.

About OctoAI

OctoAI provides infrastructure to run GenAI at scale, efficiently, and robustly. The model endpoints that OctoAI delivers to serve models like Mixtral, Stable Diffusion XL, etc. all rely on Docker to containerize models and make them easier to serve at scale. 

If you go to octoai.cloud, you’ll find three complementary solutions that developers can build on to bring their GenAI-powered apps and pipelines into production. 

Image Generation solution exposes endpoints and APIs to perform text to image, image to image tasks built around open source foundational models such as Stable Diffusion XL or SSD.

Text Generation solution exposes endpoints and APIs to perform text generation tasks built around open source foundational models, such as Mixtral/Mistral, Llama2, or CodeLlama.

Compute solution lets you deploy and manage any dockerized model container on capable OctoAI cloud endpoints to power your demanding GenAI needs. This compute service complements the image generation and text generation solutions by exposing infinite programmability and customizability for AI tasks that are not currently readily available on either the image generation or text generation solutions.

Disclaimer

OctoShop is built on the foundation of CLIP Interrogator and SDXL, and Mistral-7B and is therefore likely to carry forward the potential dangers inherent in these base models. It’s capable of generating unintended, unsuitable, offensive, and/or incorrect outputs. We therefore strongly recommend exercising caution and conducting comprehensive assessments before deploying this model into any practical applications.

This GenAI model workflow doesn’t work on people as it won’t preserve their likeness; the pipeline works best on scenes, objects, or animals. Solutions are available to address this problem, such as face mapping techniques (also known as face swapping), which we can containerize with Docker and deploy on OctoAI Compute solution, but that’s something to cover in another blog post.

Conclusion

This article covered the fundamentals of building a GenAI model cocktail by relying on a combination of text generation, image generation, and compute solutions powered by the portability and scalability enabled by Docker containerization. 

If you’re interested in learning more about building these kinds of GenAI model cocktails, check out the OctoAI demo page or join OctoAI on Discord to see what people have been building.

Acknowledgements

The authors acknowledge Justin Gage for his thorough review, as well as Luis Vega, Sameer Farooqui, and Pedro Toruella for their contributions to the DockerCon AI/ML Workshop 2023, which inspired this article. The authors also thank Cia Bodin and her daughter Ada for the drawing used in this blog post.

Learn more

Watch the DockerCon 2023 Docker for ML, AI, and Data Science workshop.

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Scaling Docker Compose Up

Docker Compose‘s simplicity — just run compose up — has been an integral part of developer workflows for a decade, with the first commit occurring in 2013, back when it was called Plum. Although the feature set has grown dramatically in that time, maintaining that experience has always been integral to the spirit of Compose.

In this post, we’ll walk through how to manage microservice sprawl with Docker Compose by importing subprojects from other Git repos.

Maintaining simplicity

Now, perhaps more than ever, that simplicity is key. The complexity of modern software development is undeniable regardless of whether you’re using microservices or a monolith, deploying to the cloud or on-prem, or writing in JavaScript or C. 

Compose has not kept up with this “development sprawl” and is even sometimes an obstacle when working on larger, more complex projects. Maintaining Compose to accurately represent your increasingly complex application can require its own expertise, often resulting in out-of-date configuration in YAML or complex makefile tasks.

As an open source project, Compose serves everyone from home lab enthusiasts to transcontinental corporations, which is no small feat, and our commitment to maintaining Compose’s signature simplicity for all users hasn’t changed.

The increased flexibility afforded by Compose watch and include means your project no longer needs to be one-size-fits-all. Now, it’s possible to split your project across Git repos and import services as needed, customizing their configuration in the process.

Application architecture

Let’s take a look at a hypothetical application architecture. To begin, the application is split across two Git repos:

backend — Backend in Python/Flask

frontend — Single-page app (SPA) frontend in JavaScript/Node.js

While working on the frontend, the developers run without using Docker or Compose, launching npm start on their laptops directly and proxy API requests to a shared staging server (as opposed to running the backend locally). Meanwhile, while working on the backend, developers and CI (for integration tests) share a Compose file and rely on command-line tools like cURL to manually test functionality locally.

We’d like a flexible configuration that enables each group of developers to use their optimal workflow (e.g., leveraging hot reload for the frontend) while also allowing reuse to share project configuration between repos. At first, this seems like an impossible situation to resolve.

Frontend

We can start by adding a compose.yaml file to frontend:

services:
frontend:
pull_policy: build
build:
context: .
environment:
BACKEND_HOST: ${BACKEND_HOST:-https://staging.example.com}
ports:
– 8000:8000

Note: If you’re wondering what the Dockerfile looks like, take a look at this samples page for an up-to-date example of best practices generated by docker init.

This is a great start! Running docker compose up will now build the Node.js frontend and make it accessible at http://localhost:8000/.

The BACKEND_HOST environment variable can be used to control where upstream API requests are proxied to and defaults to our shared staging instance.

Unfortunately, we’ve lost the great developer experience afforded by hot module reload (HMR) because everything is inside the container. By adding a develop.watch section, we can preserve that:

services:
frontend:
pull_policy: build
build:
context: .
environment:
BACKEND_HOST: ${BACKEND_HOST:-https://staging.example.com}
ports:
– 8000:8000
develop:
watch:
– path: package.json
action: rebuild
– path: src/
target: /app/src
action: sync

Now, while working on the frontend, developers continue to benefit from the rapid iteration cycles due to HMR. Whenever a file is modified locally in the src/ directory, it’s synchronized into the container at /app/src. 

If the package.json file is modified, the entire container is rebuilt, so that the RUN npm install step in the Dockerfile will be re-executed and install the latest dependencies. The best part is the only change to the workflow is running docker compose watch instead of npm start.

Backend

Now, let’s set up a Compose file in backend:

services:
backend:
pull_policy: build
build:
context: .
ports:
– 1234:8080
develop:
watch:
– path: requirements.txt
action: rebuild
– path: ./
target: /app/
action: sync

include:
– path: git@github.com:myorg/frontend.git
env_file: frontend.env

frontend.env

BACKEND_HOST=http://backend:8080

Much of this looks very similar to the frontend compose.yaml.

When files in the project directory change locally, they’re synchronized to /app inside the container, so the Flask dev server can handle hot reload. If the requirements.txt is changed, the entire container is rebuilt, so that the RUN pip install step in the Dockerfile will be re-executed and install the latest dependencies.

However, we’ve also added an include section that references the frontend project by its Git repository. The custom env_file points to a local path (in the backend repo), which sets BACKEND_HOST so that the frontend service container will proxy API requests to the backend service container instead of the default.

Note: Remote includes are an experimental feature. You’ll need to set COMPOSE_EXPERIMENTAL_GIT_REMOTE=1 in your environment to use Git references.

With this configuration, developers can now run the full stack while keeping the frontend and backend Compose projects independent and even in different Git repositories.

As developers, we’re used to sharing code library dependencies, and the include keyword brings this same reusability and convenience to your Compose development configurations.

What’s next?

There are still some rough edges. For example, the remote project is cloned to a temporary directory, which makes it impractical to use with watch mode when imported, as the files are not available for editing. Enabling bigger and more complex software projects to use Compose for flexible, personal environments is something we’re continuing to improve upon.

If you’re a Docker customer using Compose across microservices or repositories, we’d love to hear how we can better support you. Get in touch!

Learn more

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Streamline Dockerization with Docker Init GA

In May 2023, Docker announced the beta release of docker init, a new command-line interface (CLI) tool in Docker Desktop designed to streamline the Docker setup process for various types of applications and help users containerize their existing projects. We’re now excited to announce the general availability of docker init, with support for multiple languages and stacks, making it simpler than ever to containerize your applications.

What is docker init?

Initially released in its beta form in Docker 4.18, docker init has undergone several enhancements. docker init is a command-line utility that aids in the initialization of Docker resources within a project. It automatically generates Dockerfiles, Compose files, and .dockerignore files based on the nature of the project, significantly reducing the setup time and complexity associated with Docker configurations. 

The initial beta release of init came with support only for Go and generic projects. The latest version, available in Docker Desktop 4.27, supports Go, Python, Node.js, Rust, ASP.NET, PHP, and Java.

How to use docker init

Using docker init is straightforward and involves a few simple steps. Start by navigating to your project directory where you want the Docker assets to be initialized. In the terminal, execute the docker init command. This command initiates the tool and prepares it to analyze your project (Figure 1).

Figure 1: Docker init will suggest the best template for the application.

docker init will scan your project and ask you to confirm and choose the template that best suits your application. Once you select the template, docker init asks you for some project-specific information, automatically generating the necessary Docker resources for your project (Figure 2).

Figure 2. Once a template is applied, you’ll be ready to run your application with Compose.

This step includes creating a Dockerfile and a Compose file tailored to the language and framework of your choice, as well as other relevant files. The last step is to run docker-compose up to start your newly containerized project.

Why use docker init?

The docker init tool simplifies the process of dockerization, making it accessible even to those new to Docker. It eliminates the need to manually write Dockerfiles and other configuration files from scratch, saving time and reducing the potential for errors. With its template-based approach, docker init ensures that the Docker setup is optimized for the specific type of application you are working on and that your project will follow the industry’s best practices.

Conclusion

The general availability of docker init offers an efficient and user-friendly way to integrate Docker into your projects. Whether you’re a seasoned Docker user or new to containerization, docker init is set to enhance your development workflow. 

Learn more 

New to Docker? Start by downloading Docker Desktop.

Watch the following video tutorials for further insight on leveraging docker init: 

Docker init — Docker short tutorial

Docker init with Python

Docker init with Rust

Build an AI App with FastAPI and Docker — Coding Tutorial with Tips

Let’s Discover: Docker init command

Docker init support for .NET applications

Quelle: https://blog.docker.com/feed/

See 2-10x Faster File Operation Speeds with Synchronized File Shares in Docker Desktop

We are happy to announce that Mutagen’s file-sharing technology, acquired by Docker, has been seamlessly integrated into Docker Desktop, and the synchronized file shares feature is available now in Docker Desktop. This enhancement brings fast and flexible host-to-VM file sharing, offering a performance boost for developers dealing with extensive codebases.

Synchronized file shares overcome the limitations of traditional bind mounts, providing native file system performance, so developers can enjoy 2-10x faster file operation speeds. Simply log in to Docker Desktop with your subscription account (Docker Pro, Teams, or Business) to experience this new time-saving feature.

Improving the developer experience 

Synchronized file shares transform the backend developer experience by increasing developer productivity with the time saved compared to traditional file-sharing systems. Synchronized file sharing is ideal for developers who:

Manage large repositories or monorepos with more than 100,000 files, totaling significant storage.

Utilize virtual file systems (such as VirtioFS, gRPC FUSE, or osxfs) and face scalability issues with their workflows.

Encounter performance limitations and want a seamless file-sharing solution without worrying about ownership conflicts.

To get started, go to Settings and navigate to the File sharing tab within the Resources section (Figure 1). You can learn more about the functionality and how to use it in our documentation.

Figure 1: File sharing — shares have been created and are available for use in containers.

How Docker solves the problem 

Using synchronized file system caches to improve bind mount performance isn’t a new idea, but this functionality has never been available to developers as an ergonomic first-party solution. With Docker’s acquisition of Mutagen, we’re now in a position to offer an easy-to-use and transparent mechanism with potentially order-of-magnitude improvements to developer workflows.

Bind mounts are the mechanism that Linux uses to make files (like code, scripts, and images) available to containers. They’re what you get when you specify a host path to the -v/–volume flag in docker run or docker create commands (or a host path under volumes: in Compose). If folders are bind-mounted in read/write mode (the default), they also allow containers to write back to the host file system, which is great for getting files (like build products) out of containers.

When using containers natively on Linux, for example with Docker Engine, this functionality is enabled by the Linux kernel and comes with no performance impact. When using a cross-platform solution like Docker Desktop, the necessity of virtualization means that an additional file-sharing mechanism between the host system, and the Linux VM is required to enable bind mounts.

Historically, Docker has used a number of virtual file system solutions to enable this host/VM file sharing, with different solutions available based on the host platform. The most recent of these mechanisms, VirtioFS, provides an excellent out-of-the-box file-sharing solution for most developers and projects, and we’re continuing to invest in further performance improvements. These virtual file systems operate by running a file server on the host, providing files on demand via FUSE-backed file systems within the VM.

Although virtual file systems work great for most cases, there are projects where additional performance is required. In cases where a project contains many thousands (or even millions) of files totaling hundreds of megabytes or gigabytes, the demanding system calls used by development tools can lead to extremely slow behavior. 

Your project might fall into this category even if it contains only a single file — look at the staggering tree of dependencies that modern frameworks bring into your node_modules directory, for example.  Modern developer tools like compilers, dynamic language runtimes, and package managers love to traverse file systems, issuing thousands or millions of readdir(), stat(), and open()/read()/write()/close() calls. With virtual file systems, each of these system calls has to be sent across the host/VM boundary (in addition to incurring the standard round trips between kernel space and user space within the Linux VM when using the FUSE stack).

Using synchronized file shares

This is where synchronized file shares come into play. With synchronized file shares, developers can create ext4-backed caches of host file system locations inside the Docker Desktop VM. This means all those expensive file system calls are now handled directly by the Linux kernel on a native file system. These caches are kept in sync with the host file system using the Mutagen file synchronization engine, so the files are propagated bidirectionally with ultra-low latency. For most developers, there should be no perceptible difference in the file-sharing experience, other than improved performance!

So what’s the trade-off? Well, you’ll pay to store the files twice (the originals on the host and the cache inside the VM). Given the relatively low cost of disk space, compared with the high cost of developer time, this trade-off is usually a no-brainer.

To keep you in control of what gets synced, we’ve made synchronized file shares a granular, opt-in experience (we don’t want to sync your entire hard drive by default). We’ve worked hard to make this step as easy as possible — select Create share in the File sharing settings pane and choose the location you want.

The opt-in nature of synchronized file shares also makes it easy to adopt either gradually or selectively — there’s no need to impose changes on your entire team. Any bind mount that can’t be provided by synchronized file shares’ caches will fall back to your default virtual file-sharing mechanism, meaning there’s no change to your existing workflows. Team members can opt-in to synchronized file shares as necessary, using the functionality as a strategic optimization for specific parts of a codebase.

Conclusion 

We’re excited about this latest time-saving feature and what it means to you — freeing up time, increasing productivity, and enabling a focus on innovation. Docker Desktop continues investing in modernizing the developer experience, and synchronized file shares is the latest enhancement. 

Learn more  

Read the synchronized file shares documentation.

Read the Docker Desktop release notes.

Get the latest release of Docker Desktop.

New to Docker? Get started.

Have questions? The Docker community is here to help.

Quelle: https://blog.docker.com/feed/

Docker Joins the AWS ISV Accelerate Program

Docker, a long-standing partner of Amazon Web Services, has offered products on the AWS Marketplace for years. After significant growth in Docker orders through the AWS marketplace, at the beginning of 2024, Docker achieved an elevated status by joining the exclusive tier of ISVs within the AWS ISV Accelerate Program. 

This strategic move opens a new chapter for Docker and our customers, who will benefit from an integrated go-to-market approach between Docker and AWS.

Advantages of embracing the AWS ISV Accelerate Program include:

Strategic collaboration

The program fosters a deeper collaboration between Docker and AWS, creating a unique platform for both parties to work closely with AWS experts. This collaboration is pivotal for optimizing Docker’s solutions for AWS services, ensuring deployment and an enhanced onboarding experience for customers.

Market expansion

Leveraging existing agreements with AWS, customers can easily procure Docker’s offerings, capitalizing on benefits like AWS Marketplace Enterprise Discounts (EDP) and simplified procurement processes. With both go-to-market teams working closely together, customers will benefit from more tailored solutions. 

Technical enablement

The AWS ISV Accelerate Program provides Docker with a wealth of technical resources and guidance, empowering us to enhance product offerings tailored for AWS customers. From comprehensive training on AWS services to best practices and meticulous architectural reviews, Docker is well-equipped to ensure our solutions are compatible and optimized for the cloud.

Conclusion

Docker’s entry into the AWS ISV Accelerate Program marks a significant milestone in our collaborative journey with AWS. The program’s robust support structure, coupled with AWS’s unparalleled global reach, propels Docker into a position where we are accelerating our growth and actively supporting our customers in delivering an exceptional developer experience.

If you are a customer eager to explore the benefits of this dynamic partnership, we encourage you to reach out to your dedicated Docker Account Executive or contact sales. Unleash the power of this collaboration and deliver great developer experiences to your teams.

Learn more

Get the latest release of Docker Desktop.

Vote on what’s next! Check out our public roadmap.

Have questions? The Docker community is here to help.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/

Docker Security Advisory: Multiple Vulnerabilities in runc, BuildKit, and Moby

We at Docker prioritize the security and integrity of our software and the trust of our users. Security researchers at Snyk Labs recently identified and reported four security vulnerabilities in the container ecosystem. One of the vulnerabilities, CVE-2024-21626, concerns the runc container runtime, and the other three affect BuildKit (CVE-2024-23651, CVE-2024-23652, and CVE-2024-23653). We want to assure our community that our team, in collaboration with the reporters and open source maintainers, has been diligently working on coordinating and implementing necessary remediations.

We are committed to maintaining the highest security standards. We will publish patched versions of runc, BuildKit, and Moby on January 31 and release an update for Docker Desktop on February 1 to address these vulnerabilities.  Additionally, our latest Moby and BuildKit releases will include fixes for CVE-2024-23650 and CVE-2024-24557, discovered respectively by an independent researcher and through Docker’s internal research initiatives.

 Versions impactedrunc<= 1.1.11BuildKit<= 0.12.4Moby (Docker Engine)<= v25.0.1 and <= v24.0.8Docker Desktop<= 4.27.0

These vulnerabilities can only be exploited if a user actively engages with malicious content by incorporating it into the build process or running a container from a suspect image (particularly relevant for the CVE-2024-21626 container escape vulnerability). Potential impacts include unauthorized access to the host filesystem, compromising the integrity of the build cache, and, in the case of CVE-2024-21626, a scenario that could lead to full container escape. 

We strongly urge all customers to prioritize security by applying the available updates as soon as they are released. Timely application of these updates is the most effective measure to safeguard your systems against these vulnerabilities and maintain a secure and reliable Docker environment.

What should I do if I’m on an affected version?

If you are using affected versions of runc, BuildKit, Moby, or Docker Desktop, make sure to update to the latest versions as soon as patched versions become available:

 Patched versionsrunc>= 1.1.11BuildKit>= 0.12.5Moby (Docker Engine)>= v25.0.2 and >= v24.0.9Docker Desktop>= 4.27.1

If you are unable to update to an unaffected version promptly after it is released, follow these best practices to mitigate risk: 

Only use trusted Docker images (such as Docker Official Images).

Don’t build Docker images from untrusted sources or untrusted Dockerfiles.

If you are a Docker Business customer using Docker Desktop and unable to update to v4.27.1 immediately after it’s released, make sure to enable Hardened Docker Desktop features such as:

Enhanced Container Isolation, which mitigates the impact of CVE-2024-21626 in the case of running containers from malicious images.

Image Access Management, and Registry Access Management, which give organizations control over which images and repositories their users can access.

For CVE-2024-23650, CVE-2024-23651, CVE-2024-23652, and CVE-2024-23653, avoid using BuildKit frontend from an untrusted source. A frontend image is usually specified as the #syntax line on your Dockerfile, or with –frontend flag when using the buildctl build command.

To mitigate CVE-2024-24557, make sure to either use BuildKit or disable caching when building images. From the CLI this can be done via the DOCKER_BUILDKIT=1 environment variable (default for Moby >= v23.0 if the buildx plugin is installed) or the –no-cache flag. If you are using the HTTP API directly or through a client, the same can be done by setting nocache to true or version to 2 for the /build API endpoint.

Technical details and impact

CVE-2024-21626 (High)

In runc v1.1.11 and earlier, due to certain leaked file descriptors, an attacker can gain access to the host filesystem by causing a newly-spawned container process (from runc exec) to have a working directory in the host filesystem namespace, or by tricking a user to run a malicious image and allow a container process to gain access to the host filesystem through runc run. The attacks can also be adapted to overwrite semi-arbitrary host binaries, allowing for complete container escapes. Note that when using higher-level runtimes (such as Docker or Kubernetes), this vulnerability can be exploited by running a malicious container image without additional configuration or by passing specific workdir options when starting a container. The vulnerability can also be exploited from within Dockerfiles in the case of Docker.

The issue has been fixed in runc v1.1.12.

CVE-2024-23651 (High)

In BuildKit <= v0.12.4, two malicious build steps running in parallel sharing the same cache mounts with subpaths could cause a race condition, leading to files from the host system being accessible to the build container. This will only occur if a user is trying to build a Dockerfile of a malicious project.

The issue will be fixed in BuildKit v0.12.5.

CVE-2024-23652 (High)

In BuildKit <= v0.12.4, a malicious BuildKit frontend or Dockerfile using RUN –mount could trick the feature that removes empty files created for the mountpoints into removing a file outside the container from the host system. This will only occur if a user is using a malicious Dockerfile.

The issue will be fixed in BuildKit v0.12.5.

CVE-2024-23653 (High)

In addition to running containers as build steps, BuildKit also provides APIs for running interactive containers based on built images. In BuildKit <= v0.12.4, it is possible to use these APIs to ask BuildKit to run a container with elevated privileges. Normally, running such containers is only allowed if special security.insecure entitlement is enabled both by buildkitd configuration and allowed by the user initializing the build request.

The issue will be fixed in BuildKit v0.12.5.

CVE-2024-23650 (Medium)

In BuildKit <= v0.12.4, a malicious BuildKit client or frontend could craft a request that could lead to BuildKit daemon crashing with a panic.

The issue will be fixed in BuildKit v0.12.5.

CVE-2024-24557 (Medium)

In Moby <= v25.0.1 and <= v24.0.8, the classic builder cache system is prone to cache poisoning if the image is built FROM scratch. Also, changes to some instructions (most important being HEALTHCHECK and ONBUILD) would not cause a cache miss. An attacker with knowledge of the Dockerfile someone is using could poison their cache by making them pull a specially crafted image that would be considered a valid cache candidate for some build steps.

The issue will be fixed in Moby >= v25.0.2 and >= v24.0.9.

How are Docker products affected? 

The following Docker products are affected. No other products are affected by these vulnerabilities.

Docker Desktop

Docker Desktop v4.27.0 and earlier are affected. Docker Desktop v4.27.1 will be released on February 1 and includes runc, BuildKit, and dockerd binaries patches. In addition to updating to this new version, we encourage all Docker users to diligently use Docker images and Dockerfiles and ensure you only use trusted content in your builds.

Docker Build Cloud

Any new Docker Build Cloud builder instances will be provisioned with the latest Docker Engine and BuildKit versions after fixes are released and will, therefore, be unaffected by these CVEs. Docker will also be rolling out gradual updates to any existing builder instances.

Security at Docker

At Docker, we know that part of being developer-obsessed is providing secure software to developers. We appreciate the responsible disclosure of these vulnerabilities. If you’re aware of potential security vulnerabilities in any Docker product, report them to security@docker.com. For more information on Docker’s security practices, see our website.

Advisory links

Runc

CVE-2024-21626

BuildKit

CVE-2024-23650

CVE-2024-23651

CVE-2024-23652

CVE-2024-23653

Moby

CVE-2024-24557

Quelle: https://blog.docker.com/feed/

EJBCA and Docker — Streamlining PKI Management and TLS Certificate Issuance

This post was contributed by Keyfactor.Docker has revolutionized how we develop and deploy modern applications, making it easier and more efficient for developers to create and manage containerized applications. 

If you’re in the world of enterprise-level security, public key infrastructure (PKI), and certificate management, you might already be familiar with EJBCA, an open source tool for implementing PKIs. In this blog post, we will explore how to deploy EJBCA as a Docker container, making your infrastructure setup more modern, efficient, and flexible for your security and certificate management needs. 

Why deploy EJBCA as a Docker container?

EJBCA is a robust PKI and certificate management solution, but sometimes setting up and managing it can be challenging, especially if you need to deploy it from source. Deploying EJBCA as a Docker container can simplify the process and offer various benefits, including:

Portability — Docker containers are lightweight and portable, containing all the software needed to run an application. Once you have an EJBCA container image, you can run it on any system that supports Docker, ensuring consistency across environments.

Easy scaling — Containers make it straightforward to scale your EJBCA instance. You can spin up multiple containers with ease, and orchestration tools like Kubernetes can manage the scaling for you.

Simplified deployment — With EJBCA in a Docker container, you can deploy and upgrade it quickly without worrying about complex installation procedures or dependencies such as Java, database drivers, Wildfly application server, operating system, etc. An installation of EJBCA requires all of these components, and the container has all of these critical dependencies installed and configured.

Advantages of open source PKI and EJBCA

When it comes to implementing a PKI solution, EJBCA’s open source nature provides distinct advantages over other software tools or utilities. Tools such as OpenSSL may serve well for testing, but they often prove inadequate for production. A Microsoft PKI or other PKI service tailored to specific use cases can be robust but often limited in flexibility, scalability, interoperability, and compliance.

EJBCA is one of the most used open source PKIs in the world. It can be built from source using the code from GitHub or be deployed as a Docker container. Here are advantages that you can expect from EJBCA:

Comprehensive feature set — EJBCA offers a comprehensive feature set for certificate management, including certificate issuance, revocation, and key management for many use cases. You can run hundreds of CAs in one single installation. This is effective compared to, for example, Microsoft ADCS, which can run only one CA per server installation. One installation of EJBCA can also support multiple use cases.

Robust certificate authority — EJBCA functions as a full-fledged certificate authority (CA), registration authority, and validation authority, including support for both online certificate status protocol (OCSP) and certificate revocation lists (CRLs), essential for being able to support a serious PKI. 

Scalability and automation — In production scenarios, scalability is critical when EJBCA is under load and more instances are needed to serve PKI operations. EJBCA can be easily scaled using Docker orchestration tools, Helm charts, and by leveraging EJBCA open source Ansible playbooks, ensuring that your PKI infrastructure can handle the demands of your organization. 

User management and role-based access control — EJBCA offers user management and role-based access control, allowing you to define who can perform specific tasks within your PKI. 

Active community and support — EJBCA benefits from an active open source community and professional support options for the EJBCA Enterprise editions, ensuring you can find the right assistance when needed. EJBCA Enterprise edition is available as software and hardware appliances, Cloud AWS and Azure Marketplace options, and SaaS.

Compliance and auditing — EJBCA is designed with compliance and auditing in mind, helping you meet regulatory requirements and maintain a robust and signed audit trail. For example, you can enforce certificate policy for each CA to prevent the CA from signing any type of certificate signing request (CSR) that is submitted.

Getting started

Let’s walk through the process of deploying EJBCA as a Docker container. You can learn more through our introductory video on YouTube.

Step 1: Install Docker

You must have Docker installed on your system. 

Step 2: Pull the EJBCA Docker image

EJBCA provides an official Docker image, making it easy to get started. You can pull the image using the following command:

docker pull keyfactor/ejbca-ce:latest

Step 3: Run EJBCA container

Now that you have the EJBCA image, you can run it as a container:

shellCopy code
docker run -d –rm –name ejbca-node1 -p 80:8080 -p 443:8443 -h "127.0.0.1" –memory="2048m" –memory-swap="2048m" –cpus="2" ejbca/ejbca-ce:8.0.0

This command will start the EJBCA container in the background, and it will be accessible at https://localhost:443/ejbca/adminweb.

Step 4: Access the EJBCA web console

Open your web browser and navigate to https://localhost/ejbca/adminweb to access the EJBCA web console.

Custom installation configuration

If you need to customize your EJBCA instance, you can mount a configuration file or use an external database with the container. This step allows you to tailor the PKI to your specific needs.

Issuing a TLS certificate as a PKI admin  

Private TLS certificates play a crucial role in authenticating users and devices within closed network environments such as enterprise networks and business applications. When public trust isn’t necessary, opting for private TLS certificates is the most cost efficient and convenient way. Yet, it’s crucial to approach it with seriousness. The PKI software setup and certificate issuance process hold significance even in private trust environments.  

You can generate TLS client or server certificates easily by following our best practices video tutorials. EJBCA allows you to initiate on a small scale and expand as your use case evolves. This series commences with a guide on setting up EJBCA as a Docker container. Read more and find additional options for how to issue your TLS certificates with EJBCA on the website.

Conclusion

Deploying EJBCA as a Docker container simplifies the management of your PKI setup. It provides portability, isolation, and scalability, making it easier to handle security and certificate management. Whether you are a security professional or a developer working on PKI solutions, using Docker to run EJBCA can streamline your workflow and enhance your security practices.

In this blog post, we’ve covered the basics of setting up EJBCA as a Docker container and explained how a PKI admin can configure the software to issue TLS certificates. We encourage you to explore the EJBCA documentation and tutorial videos for more advanced configurations and guidance on issuing certificates for your products or workloads. With the power of Docker and EJBCA, you can take control of your certificate authority and PKI efficiently and securely.

Now, go ahead and secure your digital world with EJBCA and Docker! If you have any questions or want to share your experiences, connect with us on the Keyfactor discussions page.

Learn more

Check out EJBCA CE on Docker Hub.

Visit the Open source EJBCA PKI product page.

New to Docker? Get started.

Quelle: https://blog.docker.com/feed/