Merge component 'engine' from git@github.com:moby/moby master

This commit is contained in:
Andrew Hsu
2017-06-01 20:46:42 +00:00
137 changed files with 1512 additions and 1528 deletions

View File

@ -120,7 +120,7 @@ RUN set -x \
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
# with a heads-up.
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
| tar -xzC /usr/local

View File

@ -98,7 +98,7 @@ RUN set -x \
# bootstrap, so we use golang-go (1.6) as bootstrap to build Go from source code.
# We don't use the official ARMv6 released binaries as a GOROOT_BOOTSTRAP, because
# not all ARM64 platforms support 32-bit mode. 32-bit mode is optional for ARMv8.
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash

View File

@ -71,7 +71,7 @@ RUN cd /usr/local/lvm2 \
# See https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
# Install Go
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" \
| tar -xzC /usr/local
ENV PATH /go/bin:/usr/local/go/bin:$PATH

View File

@ -95,7 +95,7 @@ RUN set -x \
# Install Go
# NOTE: official ppc64le go binaries weren't available until go 1.6.4 and 1.7.4
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" \
| tar -xzC /usr/local

View File

@ -88,7 +88,7 @@ RUN cd /usr/local/lvm2 \
&& make install_device-mapper
# See https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" \
| tar -xzC /usr/local

View File

@ -53,7 +53,7 @@ RUN set -x \
# IMPORTANT: If the version of Go is updated, the Windows to Linux CI machines
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
# with a heads-up.
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \
| tar -xzC /usr/local
ENV PATH /go/bin:/usr/local/go/bin:$PATH

View File

@ -161,7 +161,7 @@ SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPref
# Environment variable notes:
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
# - FROM_DOCKERFILE is used for detection of building within a container.
ENV GO_VERSION=1.8.1 `
ENV GO_VERSION=1.8.3 `
GIT_VERSION=2.11.1 `
GOPATH=C:\go `
FROM_DOCKERFILE=1

View File

@ -77,7 +77,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui
}
if runtime.GOOS != "windows" && options.SecurityOpt != nil {
return nil, fmt.Errorf("the daemon on this platform does not support --security-opt to build")
return nil, fmt.Errorf("The daemon on this platform does not support setting security options on build")
}
var buildUlimits = []*units.Ulimit{}

View File

@ -11,7 +11,7 @@ import (
)
var (
errExperimentalFeature = errors.New("This experimental feature is disabled by default. Start the Docker daemon with --experimental in order to enable it.")
errExperimentalFeature = errors.New("This experimental feature is disabled by default. Start the Docker daemon in experimental mode in order to enable it.")
)
// ExperimentalRoute defines an experimental API route that can be enabled or disabled.

View File

@ -1048,6 +1048,10 @@ definitions:
type: "string"
description: "Mount path of the volume on the host."
x-nullable: false
CreatedAt:
type: "string"
format: "dateTime"
description: "Time volume was created."
Status:
type: "object"
description: |
@ -1101,6 +1105,7 @@ definitions:
com.example.some-label: "some-value"
com.example.some-other-label: "some-other-value"
Scope: "local"
CreatedAt: "2016-06-07T20:31:11.853781916Z"
Network:
type: "object"
@ -2174,9 +2179,6 @@ definitions:
Runtime:
description: "Runtime is the type of runtime specified for the task executor."
type: "string"
RuntimeData:
description: "RuntimeData is the payload sent to be used with the runtime for the executor."
type: "array"
Networks:
type: "array"
items:
@ -3122,7 +3124,7 @@ paths:
all processes in the container. Freezing the process requires the process to
be running. As a result, paused containers are both `Running` _and_ `Paused`.
Use the `Status` field instead to determin if a container's state is "running".
Use the `Status` field instead to determine if a container's state is "running".
type: "boolean"
Paused:
description: "Whether this container is paused."

View File

@ -67,9 +67,6 @@ type TaskSpec struct {
ForceUpdate uint64
Runtime RuntimeType `json:",omitempty"`
// TODO (ehazlett): this should be removed and instead
// use struct tags (proto) for the runtimes
RuntimeData []byte `json:",omitempty"`
}
// Resources represents resources (CPU/Memory).

View File

@ -7,6 +7,9 @@ package types
// swagger:model Volume
type Volume struct {
// Time volume was created.
CreatedAt string `json:"CreatedAt,omitempty"`
// Name of the volume driver used by the volume.
// Required: true
Driver string `json:"Driver"`

View File

@ -7,12 +7,11 @@ package builder
import (
"io"
"golang.org/x/net/context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/container"
containerpkg "github.com/docker/docker/container"
"golang.org/x/net/context"
)
const (
@ -36,21 +35,10 @@ type Source interface {
// Backend abstracts calls to a Docker Daemon.
type Backend interface {
ImageBackend
ExecBackend
// ContainerAttachRaw attaches to container.
ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error
// ContainerCreate creates a new Docker container and returns potential warnings
ContainerCreate(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error)
// ContainerRm removes a container specified by `id`.
ContainerRm(name string, config *types.ContainerRmConfig) error
// Commit creates a new Docker image from an existing Docker container.
Commit(string, *backend.ContainerCommitConfig) (string, error)
// ContainerKill stops the container execution abruptly.
ContainerKill(containerID string, sig uint64) error
// ContainerStart starts a new container
ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
// ContainerWait stops processing until the given container is stopped.
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
// ContainerCreateWorkdir creates the workdir
ContainerCreateWorkdir(containerID string) error
@ -59,6 +47,8 @@ type Backend interface {
// TODO: extract in the builder instead of passing `decompress`
// TODO: use containerd/fs.changestream instead as a source
CopyOnBuild(containerID string, destPath string, srcRoot string, srcPath string, decompress bool) error
ImageCacheBuilder
}
// ImageBackend are the interface methods required from an image component
@ -66,6 +56,22 @@ type ImageBackend interface {
GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (Image, ReleaseableLayer, error)
}
// ExecBackend contains the interface methods required for executing containers
type ExecBackend interface {
// ContainerAttachRaw attaches to container.
ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error
// ContainerCreate creates a new Docker container and returns potential warnings
ContainerCreate(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error)
// ContainerRm removes a container specified by `id`.
ContainerRm(name string, config *types.ContainerRmConfig) error
// ContainerKill stops the container execution abruptly.
ContainerKill(containerID string, sig uint64) error
// ContainerStart starts a new container
ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
// ContainerWait stops processing until the given container is stopped.
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
}
// Result is the output produced by a Builder
type Result struct {
ImageID string

View File

@ -2,8 +2,9 @@ package dockerfile
import (
"fmt"
"github.com/docker/docker/runconfig/opts"
"io"
"github.com/docker/docker/runconfig/opts"
)
// builtinAllowedBuildArgs is list of built-in allowed build args

View File

@ -1,9 +1,9 @@
package dockerfile
import (
"bytes"
"testing"
"bytes"
"github.com/stretchr/testify/assert"
)

View File

@ -35,8 +35,6 @@ var validCommitCommands = map[string]bool{
"workdir": true,
}
var defaultLogConfig = container.LogConfig{Type: "none"}
// BuildManager is shared across all Builder objects
type BuildManager struct {
backend builder.Backend
@ -100,14 +98,13 @@ type Builder struct {
docker builder.Backend
clientCtx context.Context
tmpContainers map[string]struct{}
buildStages *buildStages
disableCommit bool
cacheBusted bool
buildArgs *buildArgs
imageCache builder.ImageCache
imageSources *imageSources
pathCache pathCache
buildStages *buildStages
disableCommit bool
buildArgs *buildArgs
imageSources *imageSources
pathCache pathCache
containerManager *containerManager
imageProber ImageProber
}
// newBuilder creates a new Dockerfile builder from an optional dockerfile and a Options.
@ -117,29 +114,23 @@ func newBuilder(clientCtx context.Context, options builderOptions) *Builder {
config = new(types.ImageBuildOptions)
}
b := &Builder{
clientCtx: clientCtx,
options: config,
Stdout: options.ProgressWriter.StdoutFormatter,
Stderr: options.ProgressWriter.StderrFormatter,
Aux: options.ProgressWriter.AuxFormatter,
Output: options.ProgressWriter.Output,
docker: options.Backend,
tmpContainers: map[string]struct{}{},
buildArgs: newBuildArgs(config.BuildArgs),
buildStages: newBuildStages(),
imageSources: newImageSources(clientCtx, options),
pathCache: options.PathCache,
clientCtx: clientCtx,
options: config,
Stdout: options.ProgressWriter.StdoutFormatter,
Stderr: options.ProgressWriter.StderrFormatter,
Aux: options.ProgressWriter.AuxFormatter,
Output: options.ProgressWriter.Output,
docker: options.Backend,
buildArgs: newBuildArgs(config.BuildArgs),
buildStages: newBuildStages(),
imageSources: newImageSources(clientCtx, options),
pathCache: options.PathCache,
imageProber: newImageProber(options.Backend, config.CacheFrom, config.NoCache),
containerManager: newContainerManager(options.Backend),
}
return b
}
func (b *Builder) resetImageCache() {
if icb, ok := b.docker.(builder.ImageCacheBuilder); ok {
b.imageCache = icb.MakeImageCache(b.options.CacheFrom)
}
b.cacheBusted = false
}
// Build runs the Dockerfile builder by parsing the Dockerfile and executing
// the instructions from the file.
func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*builder.Result, error) {
@ -216,14 +207,14 @@ func (b *Builder) dispatchDockerfileWithCancellation(dockerfile *parser.Result,
}
if state, err = b.dispatch(opts); err != nil {
if b.options.ForceRemove {
b.clearTmp()
b.containerManager.RemoveAll(b.Stdout)
}
return nil, err
}
fmt.Fprintf(b.Stdout, " ---> %s\n", stringid.TruncateID(state.imageID))
if b.options.Remove {
b.clearTmp()
b.containerManager.RemoveAll(b.Stdout)
}
}
@ -258,7 +249,9 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
return config, nil
}
b := newBuilder(context.Background(), builderOptions{})
b := newBuilder(context.Background(), builderOptions{
Options: &types.ImageBuildOptions{NoCache: true},
})
dockerfile, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n")))
if err != nil {

View File

@ -0,0 +1,143 @@
package dockerfile
import (
"fmt"
"io"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder"
containerpkg "github.com/docker/docker/container"
"github.com/docker/docker/pkg/stringid"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
type containerManager struct {
tmpContainers map[string]struct{}
backend builder.ExecBackend
}
// newContainerManager creates a new container backend
func newContainerManager(docker builder.ExecBackend) *containerManager {
return &containerManager{
backend: docker,
tmpContainers: make(map[string]struct{}),
}
}
// Create a container
func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig) (container.ContainerCreateCreatedBody, error) {
container, err := c.backend.ContainerCreate(types.ContainerCreateConfig{
Config: runConfig,
HostConfig: hostConfig,
})
if err != nil {
return container, err
}
c.tmpContainers[container.ID] = struct{}{}
return container, nil
}
var errCancelled = errors.New("build cancelled")
// Run a container by ID
func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr io.Writer) (err error) {
attached := make(chan struct{})
errCh := make(chan error)
go func() {
errCh <- c.backend.ContainerAttachRaw(cID, nil, stdout, stderr, true, attached)
}()
select {
case err := <-errCh:
return err
case <-attached:
}
finished := make(chan struct{})
cancelErrCh := make(chan error, 1)
go func() {
select {
case <-ctx.Done():
logrus.Debugln("Build cancelled, killing and removing container:", cID)
c.backend.ContainerKill(cID, 0)
c.removeContainer(cID, stdout)
cancelErrCh <- errCancelled
case <-finished:
cancelErrCh <- nil
}
}()
if err := c.backend.ContainerStart(cID, nil, "", ""); err != nil {
close(finished)
logCancellationError(cancelErrCh, "error from ContainerStart: "+err.Error())
return err
}
// Block on reading output from container, stop on err or chan closed
if err := <-errCh; err != nil {
close(finished)
logCancellationError(cancelErrCh, "error from errCh: "+err.Error())
return err
}
waitC, err := c.backend.ContainerWait(ctx, cID, containerpkg.WaitConditionNotRunning)
if err != nil {
close(finished)
logCancellationError(cancelErrCh, fmt.Sprintf("unable to begin ContainerWait: %s", err))
return err
}
if status := <-waitC; status.ExitCode() != 0 {
close(finished)
logCancellationError(cancelErrCh,
fmt.Sprintf("a non-zero code from ContainerWait: %d", status.ExitCode()))
return &statusCodeError{code: status.ExitCode(), err: err}
}
close(finished)
return <-cancelErrCh
}
func logCancellationError(cancelErrCh chan error, msg string) {
if cancelErr := <-cancelErrCh; cancelErr != nil {
logrus.Debugf("Build cancelled (%v): ", cancelErr, msg)
}
}
type statusCodeError struct {
code int
err error
}
func (e *statusCodeError) Error() string {
return e.err.Error()
}
func (e *statusCodeError) StatusCode() int {
return e.code
}
func (c *containerManager) removeContainer(containerID string, stdout io.Writer) error {
rmConfig := &types.ContainerRmConfig{
ForceRemove: true,
RemoveVolume: true,
}
if err := c.backend.ContainerRm(containerID, rmConfig); err != nil {
fmt.Fprintf(stdout, "Error removing intermediate container %s: %v\n", stringid.TruncateID(containerID), err)
return err
}
return nil
}
// RemoveAll containers managed by this container manager
func (c *containerManager) RemoveAll(stdout io.Writer) {
for containerID := range c.tmpContainers {
if err := c.removeContainer(containerID, stdout); err != nil {
return
}
delete(c.tmpContainers, containerID)
fmt.Fprintf(stdout, "Removing intermediate container %s\n", stringid.TruncateID(containerID))
}
}

View File

@ -19,11 +19,11 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/strslice"
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/dockerfile/parser"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/signal"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
@ -218,7 +218,7 @@ func from(req dispatchRequest) error {
return err
}
req.builder.resetImageCache()
req.builder.imageProber.Reset()
image, err := req.builder.getFromImage(req.shlex, req.args[0])
if err != nil {
return err
@ -398,24 +398,15 @@ func workdir(req dispatchRequest) error {
comment := "WORKDIR " + runConfig.WorkingDir
runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment))
if hit, err := req.builder.probeCache(req.state, runConfigWithCommentCmd); err != nil || hit {
containerID, err := req.builder.probeAndCreate(req.state, runConfigWithCommentCmd)
if err != nil || containerID == "" {
return err
}
if err := req.builder.docker.ContainerCreateWorkdir(containerID); err != nil {
return err
}
container, err := req.builder.docker.ContainerCreate(types.ContainerCreateConfig{
Config: runConfigWithCommentCmd,
// Set a log config to override any default value set on the daemon
HostConfig: &container.HostConfig{LogConfig: defaultLogConfig},
})
if err != nil {
return err
}
req.builder.tmpContainers[container.ID] = struct{}{}
if err := req.builder.docker.ContainerCreateWorkdir(container.ID); err != nil {
return err
}
return req.builder.commitContainer(req.state, container.ID, runConfigWithCommentCmd)
return req.builder.commitContainer(req.state, containerID, runConfigWithCommentCmd)
}
// RUN some command yo
@ -471,7 +462,16 @@ func run(req dispatchRequest) error {
if err != nil {
return err
}
if err := req.builder.run(cID, runConfig.Cmd); err != nil {
if err := req.builder.containerManager.Run(req.builder.clientCtx, cID, req.builder.Stdout, req.builder.Stderr); err != nil {
if err, ok := err.(*statusCodeError); ok {
// TODO: change error type, because jsonmessage.JSONError assumes HTTP
return &jsonmessage.JSONError{
Message: fmt.Sprintf(
"The command '%s' returned a non-zero code: %d",
strings.Join(runConfig.Cmd, " "), err.StatusCode()),
Code: err.StatusCode(),
}
}
return err
}

View File

@ -7,6 +7,7 @@ import (
"bytes"
"context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/container"
@ -54,7 +55,6 @@ func newBuilderWithMockBackend() *Builder {
options: &types.ImageBuildOptions{},
docker: mockBackend,
buildArgs: newBuildArgs(make(map[string]*string)),
tmpContainers: make(map[string]struct{}),
Stdout: new(bytes.Buffer),
clientCtx: ctx,
disableCommit: true,
@ -62,7 +62,9 @@ func newBuilderWithMockBackend() *Builder {
Options: &types.ImageBuildOptions{},
Backend: mockBackend,
}),
buildStages: newBuildStages(),
buildStages: newBuildStages(),
imageProber: newImageProber(mockBackend, nil, false),
containerManager: newContainerManager(mockBackend),
}
return b
}
@ -479,9 +481,12 @@ func TestRunWithBuildArgs(t *testing.T) {
return "", nil
},
}
b.imageCache = imageCache
mockBackend := b.docker.(*MockBackend)
mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
return imageCache
}
b.imageProber = newImageProber(mockBackend, nil, false)
mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ReleaseableLayer, error) {
return &mockImage{
id: "abcdef",

View File

@ -0,0 +1,63 @@
package dockerfile
import (
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder"
)
// ImageProber exposes an Image cache to the Builder. It supports resetting a
// cache.
type ImageProber interface {
Reset()
Probe(parentID string, runConfig *container.Config) (string, error)
}
type imageProber struct {
cache builder.ImageCache
reset func() builder.ImageCache
cacheBusted bool
}
func newImageProber(cacheBuilder builder.ImageCacheBuilder, cacheFrom []string, noCache bool) ImageProber {
if noCache {
return &nopProber{}
}
reset := func() builder.ImageCache {
return cacheBuilder.MakeImageCache(cacheFrom)
}
return &imageProber{cache: reset(), reset: reset}
}
func (c *imageProber) Reset() {
c.cache = c.reset()
c.cacheBusted = false
}
// Probe checks if cache match can be found for current build instruction.
// It returns the cachedID if there is a hit, and the empty string on miss
func (c *imageProber) Probe(parentID string, runConfig *container.Config) (string, error) {
if c.cacheBusted {
return "", nil
}
cacheID, err := c.cache.GetCache(parentID, runConfig)
if err != nil {
return "", err
}
if len(cacheID) == 0 {
logrus.Debugf("[BUILDER] Cache miss: %s", runConfig.Cmd)
c.cacheBusted = true
return "", nil
}
logrus.Debugf("[BUILDER] Use cached version: %s", runConfig.Cmd)
return cacheID, nil
}
type nopProber struct{}
func (c *nopProber) Reset() {}
func (c *nopProber) Probe(_ string, _ *container.Config) (string, error) {
return "", nil
}

View File

@ -9,12 +9,9 @@ import (
"fmt"
"strings"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/container"
containerpkg "github.com/docker/docker/container"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/pkg/stringid"
"github.com/pkg/errors"
)
@ -74,20 +71,11 @@ func (b *Builder) performCopy(state *dispatchState, inst copyInstruction) error
runConfigWithCommentCmd := copyRunConfig(
state.runConfig,
withCmdCommentString(fmt.Sprintf("%s %s in %s ", inst.cmdName, srcHash, inst.dest)))
if hit, err := b.probeCache(state, runConfigWithCommentCmd); err != nil || hit {
containerID, err := b.probeAndCreate(state, runConfigWithCommentCmd)
if err != nil || containerID == "" {
return err
}
container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{
Config: runConfigWithCommentCmd,
// Set a log config to override any default value set on the daemon
HostConfig: &container.HostConfig{LogConfig: defaultLogConfig},
})
if err != nil {
return err
}
b.tmpContainers[container.ID] = struct{}{}
// Twiddle the destination when it's a relative path - meaning, make it
// relative to the WORKINGDIR
dest, err := normaliseDest(inst.cmdName, state.runConfig.WorkingDir, inst.dest)
@ -96,11 +84,11 @@ func (b *Builder) performCopy(state *dispatchState, inst copyInstruction) error
}
for _, info := range inst.infos {
if err := b.docker.CopyOnBuild(container.ID, dest, info.root, info.path, inst.allowLocalDecompression); err != nil {
if err := b.docker.CopyOnBuild(containerID, dest, info.root, info.path, inst.allowLocalDecompression); err != nil {
return err
}
}
return b.commitContainer(state, container.ID, runConfigWithCommentCmd)
return b.commitContainer(state, containerID, runConfigWithCommentCmd)
}
// For backwards compat, if there's just one info then use it as the
@ -186,166 +174,65 @@ func getShell(c *container.Config) []string {
return append([]string{}, c.Shell[:]...)
}
// probeCache checks if cache match can be found for current build instruction.
// If an image is found, probeCache returns `(true, nil)`.
// If no image is found, it returns `(false, nil)`.
// If there is any error, it returns `(false, err)`.
func (b *Builder) probeCache(dispatchState *dispatchState, runConfig *container.Config) (bool, error) {
c := b.imageCache
if c == nil || b.options.NoCache || b.cacheBusted {
return false, nil
}
cache, err := c.GetCache(dispatchState.imageID, runConfig)
if err != nil {
cachedID, err := b.imageProber.Probe(dispatchState.imageID, runConfig)
if cachedID == "" || err != nil {
return false, err
}
if len(cache) == 0 {
logrus.Debugf("[BUILDER] Cache miss: %s", runConfig.Cmd)
b.cacheBusted = true
return false, nil
}
fmt.Fprint(b.Stdout, " ---> Using cache\n")
logrus.Debugf("[BUILDER] Use cached version: %s", runConfig.Cmd)
dispatchState.imageID = string(cache)
b.buildStages.update(dispatchState.imageID, runConfig)
dispatchState.imageID = string(cachedID)
b.buildStages.update(dispatchState.imageID, runConfig)
return true, nil
}
var defaultLogConfig = container.LogConfig{Type: "none"}
func (b *Builder) probeAndCreate(dispatchState *dispatchState, runConfig *container.Config) (string, error) {
if hit, err := b.probeCache(dispatchState, runConfig); err != nil || hit {
return "", err
}
// Set a log config to override any default value set on the daemon
hostConfig := &container.HostConfig{LogConfig: defaultLogConfig}
container, err := b.containerManager.Create(runConfig, hostConfig)
return container.ID, err
}
func (b *Builder) create(runConfig *container.Config) (string, error) {
resources := container.Resources{
CgroupParent: b.options.CgroupParent,
CPUShares: b.options.CPUShares,
CPUPeriod: b.options.CPUPeriod,
CPUQuota: b.options.CPUQuota,
CpusetCpus: b.options.CPUSetCPUs,
CpusetMems: b.options.CPUSetMems,
Memory: b.options.Memory,
MemorySwap: b.options.MemorySwap,
Ulimits: b.options.Ulimits,
}
// TODO: why not embed a hostconfig in builder?
hostConfig := &container.HostConfig{
SecurityOpt: b.options.SecurityOpt,
Isolation: b.options.Isolation,
ShmSize: b.options.ShmSize,
Resources: resources,
NetworkMode: container.NetworkMode(b.options.NetworkMode),
// Set a log config to override any default value set on the daemon
LogConfig: defaultLogConfig,
ExtraHosts: b.options.ExtraHosts,
}
// Create the container
c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{
Config: runConfig,
HostConfig: hostConfig,
})
hostConfig := hostConfigFromOptions(b.options)
container, err := b.containerManager.Create(runConfig, hostConfig)
if err != nil {
return "", err
}
for _, warning := range c.Warnings {
// TODO: could this be moved into containerManager.Create() ?
for _, warning := range container.Warnings {
fmt.Fprintf(b.Stdout, " ---> [Warning] %s\n", warning)
}
b.tmpContainers[c.ID] = struct{}{}
fmt.Fprintf(b.Stdout, " ---> Running in %s\n", stringid.TruncateID(c.ID))
return c.ID, nil
fmt.Fprintf(b.Stdout, " ---> Running in %s\n", stringid.TruncateID(container.ID))
return container.ID, nil
}
var errCancelled = errors.New("build cancelled")
func (b *Builder) run(cID string, cmd []string) (err error) {
attached := make(chan struct{})
errCh := make(chan error)
go func() {
errCh <- b.docker.ContainerAttachRaw(cID, nil, b.Stdout, b.Stderr, true, attached)
}()
select {
case err := <-errCh:
return err
case <-attached:
func hostConfigFromOptions(options *types.ImageBuildOptions) *container.HostConfig {
resources := container.Resources{
CgroupParent: options.CgroupParent,
CPUShares: options.CPUShares,
CPUPeriod: options.CPUPeriod,
CPUQuota: options.CPUQuota,
CpusetCpus: options.CPUSetCPUs,
CpusetMems: options.CPUSetMems,
Memory: options.Memory,
MemorySwap: options.MemorySwap,
Ulimits: options.Ulimits,
}
finished := make(chan struct{})
cancelErrCh := make(chan error, 1)
go func() {
select {
case <-b.clientCtx.Done():
logrus.Debugln("Build cancelled, killing and removing container:", cID)
b.docker.ContainerKill(cID, 0)
b.removeContainer(cID)
cancelErrCh <- errCancelled
case <-finished:
cancelErrCh <- nil
}
}()
if err := b.docker.ContainerStart(cID, nil, "", ""); err != nil {
close(finished)
if cancelErr := <-cancelErrCh; cancelErr != nil {
logrus.Debugf("Build cancelled (%v) and got an error from ContainerStart: %v",
cancelErr, err)
}
return err
}
// Block on reading output from container, stop on err or chan closed
if err := <-errCh; err != nil {
close(finished)
if cancelErr := <-cancelErrCh; cancelErr != nil {
logrus.Debugf("Build cancelled (%v) and got an error from errCh: %v",
cancelErr, err)
}
return err
}
waitC, err := b.docker.ContainerWait(b.clientCtx, cID, containerpkg.WaitConditionNotRunning)
if err != nil {
// Unable to begin waiting for container.
close(finished)
if cancelErr := <-cancelErrCh; cancelErr != nil {
logrus.Debugf("Build cancelled (%v) and unable to begin ContainerWait: %d", cancelErr, err)
}
return err
}
if status := <-waitC; status.ExitCode() != 0 {
close(finished)
if cancelErr := <-cancelErrCh; cancelErr != nil {
logrus.Debugf("Build cancelled (%v) and got a non-zero code from ContainerWait: %d", cancelErr, status.ExitCode())
}
// TODO: change error type, because jsonmessage.JSONError assumes HTTP
return &jsonmessage.JSONError{
Message: fmt.Sprintf("The command '%s' returned a non-zero code: %d", strings.Join(cmd, " "), status.ExitCode()),
Code: status.ExitCode(),
}
}
close(finished)
return <-cancelErrCh
}
func (b *Builder) removeContainer(c string) error {
rmConfig := &types.ContainerRmConfig{
ForceRemove: true,
RemoveVolume: true,
}
if err := b.docker.ContainerRm(c, rmConfig); err != nil {
fmt.Fprintf(b.Stdout, "Error removing intermediate container %s: %v\n", stringid.TruncateID(c), err)
return err
}
return nil
}
func (b *Builder) clearTmp() {
for c := range b.tmpContainers {
if err := b.removeContainer(c); err != nil {
return
}
delete(b.tmpContainers, c)
fmt.Fprintf(b.Stdout, "Removing intermediate container %s\n", stringid.TruncateID(c))
return &container.HostConfig{
SecurityOpt: options.SecurityOpt,
Isolation: options.Isolation,
ShmSize: options.ShmSize,
Resources: resources,
NetworkMode: container.NetworkMode(options.NetworkMode),
// Set a log config to override any default value set on the daemon
LogConfig: defaultLogConfig,
ExtraHosts: options.ExtraHosts,
}
}

View File

@ -3,13 +3,11 @@ package dockerfile
import (
"io"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder"
containerpkg "github.com/docker/docker/container"
"github.com/docker/docker/image"
"golang.org/x/net/context"
)
@ -18,10 +16,7 @@ type MockBackend struct {
containerCreateFunc func(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error)
commitFunc func(string, *backend.ContainerCommitConfig) (string, error)
getImageFunc func(string) (builder.Image, builder.ReleaseableLayer, error)
}
func (m *MockBackend) TagImageWithReference(image.ID, reference.Named) error {
return nil
makeImageCacheFunc func(cacheFrom []string) builder.ImageCache
}
func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error {
@ -74,6 +69,13 @@ func (m *MockBackend) GetImageAndReleasableLayer(ctx context.Context, refOrID st
return &mockImage{id: "theid"}, &mockLayer{}, nil
}
func (m *MockBackend) MakeImageCache(cacheFrom []string) builder.ImageCache {
if m.makeImageCacheFunc != nil {
return m.makeImageCacheFunc(cacheFrom)
}
return nil
}
type mockImage struct {
id string
config *container.Config

View File

@ -41,6 +41,7 @@ func Detect(config backend.BuildConfig) (remote builder.Source, dockerfile *pars
}
func newArchiveRemote(rc io.ReadCloser, dockerfilePath string) (builder.Source, *parser.Result, error) {
defer rc.Close()
c, err := MakeTarSumContext(rc)
if err != nil {
return nil, nil, err

View File

@ -6,7 +6,6 @@ import (
"path/filepath"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/cli"
"github.com/docker/docker/opts"
"github.com/docker/go-connections/tlsconfig"
"github.com/spf13/pflag"
@ -46,7 +45,7 @@ func NewCommonOptions() *CommonOptions {
// InstallFlags adds flags for the common options on the FlagSet
func (commonOpts *CommonOptions) InstallFlags(flags *pflag.FlagSet) {
if dockerCertPath == "" {
dockerCertPath = cli.ConfigurationDir()
dockerCertPath = ConfigurationDir()
}
flags.BoolVarP(&commonOpts.Debug, "debug", "D", false, "Enable debug mode")

View File

@ -4,7 +4,6 @@ import (
"path/filepath"
"testing"
"github.com/docker/docker/cli"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)
@ -26,7 +25,7 @@ func TestCommonOptionsInstallFlags(t *testing.T) {
}
func defaultPath(filename string) string {
return filepath.Join(cli.ConfigurationDir(), filename)
return filepath.Join(ConfigurationDir(), filename)
}
func TestCommonOptionsInstallFlagsWithDefaults(t *testing.T) {

View File

@ -1,4 +1,4 @@
package cli
package flags
import (
"os"

View File

@ -247,6 +247,12 @@ func (cli *Client) UpdateClientVersion(v string) {
}
// DaemonHost returns the host associated with this instance of the Client.
// This operation doesn't acquire a mutex.
func (cli *Client) DaemonHost() string {
return cli.host
}
// ParseHost verifies that the given host strings is valid.
func ParseHost(host string) (string, string, string, error) {
protoAddrParts := strings.SplitN(host, "://", 2)

View File

@ -10,7 +10,7 @@ import (
"github.com/docker/docker/api/types/versions"
)
// ContainerWait waits until the specified continer is in a certain state
// ContainerWait waits until the specified container is in a certain state
// indicated by the given condition, either "not-running" (default),
// "next-exit", or "removed".
//

View File

@ -31,6 +31,7 @@ type CommonAPIClient interface {
SystemAPIClient
VolumeAPIClient
ClientVersion() string
DaemonHost() string
ServerVersion(ctx context.Context) (types.Version, error)
UpdateClientVersion(v string)
}

View File

@ -24,14 +24,18 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth}
}
// ensure that the image is tagged
if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
service.TaskTemplate.ContainerSpec.Image = taggedImg
}
// Contact the registry to retrieve digest and platform information
if options.QueryRegistry {
distributionInspect, err := cli.DistributionInspect(ctx, service.TaskTemplate.ContainerSpec.Image, options.EncodedRegistryAuth)
distErr = err
if err == nil {
// now pin by digest if the image doesn't already contain a digest
img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest)
if img != "" {
if img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest); img != "" {
service.TaskTemplate.ContainerSpec.Image = img
}
// add platforms that are compatible with the service
@ -55,22 +59,33 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
}
// imageWithDigestString takes an image string and a digest, and updates
// the image string if it didn't originally contain a digest. It assumes
// that the image string is not an image ID
// the image string if it didn't originally contain a digest. It returns
// an empty string if there are no updates.
func imageWithDigestString(image string, dgst digest.Digest) string {
ref, err := reference.ParseAnyReference(image)
namedRef, err := reference.ParseNormalizedNamed(image)
if err == nil {
if _, isCanonical := ref.(reference.Canonical); !isCanonical {
namedRef, _ := ref.(reference.Named)
if _, isCanonical := namedRef.(reference.Canonical); !isCanonical {
// ensure that image gets a default tag if none is provided
img, err := reference.WithDigest(namedRef, dgst)
if err == nil {
return img.String()
return reference.FamiliarString(img)
}
}
}
return ""
}
// imageWithTagString takes an image string, and returns a tagged image
// string, adding a 'latest' tag if one was not provided. It returns an
// emptry string if a canonical reference was provided
func imageWithTagString(image string) string {
namedRef, err := reference.ParseNormalizedNamed(image)
if err == nil {
return reference.FamiliarString(reference.TagNameOnly(namedRef))
}
return ""
}
// updateServicePlatforms updates the Platforms in swarm.Placement to list
// all compatible platforms for the service, as found in distributionInspect
// and returns a pointer to the new or updated swarm.Placement struct

View File

@ -13,6 +13,7 @@ import (
"github.com/docker/docker/api/types"
registrytypes "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/api/types/swarm"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1"
"golang.org/x/net/context"
)
@ -121,3 +122,92 @@ func TestServiceCreateCompatiblePlatforms(t *testing.T) {
t.Fatalf("expected `service_amd64`, got %s", r.ID)
}
}
func TestServiceCreateDigestPinning(t *testing.T) {
dgst := "sha256:c0537ff6a5218ef531ece93d4984efc99bbf3f7497c0a7726c88e2bb7584dc96"
dgstAlt := "sha256:37ffbf3f7497c07584dc9637ffbf3f7497c0758c0537ffbf3f7497c0c88e2bb7"
serviceCreateImage := ""
pinByDigestTests := []struct {
img string // input image provided by the user
expected string // expected image after digest pinning
}{
// default registry returns familiar string
{"docker.io/library/alpine", "alpine:latest@" + dgst},
// provided tag is preserved and digest added
{"alpine:edge", "alpine:edge@" + dgst},
// image with provided alternative digest remains unchanged
{"alpine@" + dgstAlt, "alpine@" + dgstAlt},
// image with provided tag and alternative digest remains unchanged
{"alpine:edge@" + dgstAlt, "alpine:edge@" + dgstAlt},
// image on alternative registry does not result in familiar string
{"alternate.registry/library/alpine", "alternate.registry/library/alpine:latest@" + dgst},
// unresolvable image does not get a digest
{"cannotresolve", "cannotresolve:latest"},
}
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if strings.HasPrefix(req.URL.Path, "/services/create") {
// reset and set image received by the service create endpoint
serviceCreateImage = ""
var service swarm.ServiceSpec
if err := json.NewDecoder(req.Body).Decode(&service); err != nil {
return nil, fmt.Errorf("could not parse service create request")
}
serviceCreateImage = service.TaskTemplate.ContainerSpec.Image
b, err := json.Marshal(types.ServiceCreateResponse{
ID: "service_id",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
} else if strings.HasPrefix(req.URL.Path, "/distribution/cannotresolve") {
// unresolvable image
return nil, fmt.Errorf("cannot resolve image")
} else if strings.HasPrefix(req.URL.Path, "/distribution/") {
// resolvable images
b, err := json.Marshal(registrytypes.DistributionInspect{
Descriptor: v1.Descriptor{
Digest: digest.Digest(dgst),
},
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(bytes.NewReader(b)),
}, nil
}
return nil, fmt.Errorf("unexpected URL '%s'", req.URL.Path)
}),
}
// run pin by digest tests
for _, p := range pinByDigestTests {
r, err := client.ServiceCreate(context.Background(), swarm.ServiceSpec{
TaskTemplate: swarm.TaskSpec{
ContainerSpec: swarm.ContainerSpec{
Image: p.img,
},
},
}, types.ServiceCreateOptions{QueryRegistry: true})
if err != nil {
t.Fatal(err)
}
if r.ID != "service_id" {
t.Fatalf("expected `service_id`, got %s", r.ID)
}
if p.expected != serviceCreateImage {
t.Fatalf("expected image %s, got %s", p.expected, serviceCreateImage)
}
}
}

View File

@ -35,6 +35,11 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
query.Set("version", strconv.FormatUint(version.Index, 10))
// ensure that the image is tagged
if taggedImg := imageWithTagString(service.TaskTemplate.ContainerSpec.Image); taggedImg != "" {
service.TaskTemplate.ContainerSpec.Image = taggedImg
}
// Contact the registry to retrieve digest and platform information
// This happens only when the image has changed
if options.QueryRegistry {
@ -42,8 +47,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
distErr = err
if err == nil {
// now pin by digest if the image doesn't already contain a digest
img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest)
if img != "" {
if img := imageWithDigestString(service.TaskTemplate.ContainerSpec.Image, distributionInspect.Descriptor.Digest); img != "" {
service.TaskTemplate.ContainerSpec.Image = img
}
// add platforms that are compatible with the service

View File

@ -13,6 +13,7 @@ import (
containertypes "github.com/docker/docker/api/types/container"
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/symlink"
"github.com/docker/docker/pkg/system"
@ -220,7 +221,9 @@ func (container *Container) UnmountIpcMounts(unmount func(pth string) error) {
warnings = append(warnings, err.Error())
} else if shmPath != "" {
if err := unmount(shmPath); err != nil && !os.IsNotExist(err) {
warnings = append(warnings, fmt.Sprintf("failed to umount %s: %v", shmPath, err))
if mounted, mErr := mount.Mounted(shmPath); mounted || mErr != nil {
warnings = append(warnings, fmt.Sprintf("failed to umount %s: %v", shmPath, err))
}
}
}

View File

@ -180,7 +180,7 @@ const (
WaitConditionRemoved
)
// Wait waits until the continer is in a certain state indicated by the given
// Wait waits until the container is in a certain state indicated by the given
// condition. A context must be used for cancelling the request, controlling
// timeouts, and avoiding goroutine leaks. Wait must be called without holding
// the state lock. Returns a channel from which the caller will receive the

View File

@ -12,7 +12,7 @@ RUN update-alternatives --install /usr/bin/go go /usr/lib/go-1.6/bin/go 100
# Install Go
# aarch64 doesn't have official go binaries, so use the version of go installed from
# the image to build go from source.
ENV GO_VERSION 1.7.5
ENV GO_VERSION 1.8.3
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash

View File

@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools bu
# Install Go
# aarch64 doesn't have official go binaries, so use the version of go installed from
# the image to build go from source.
ENV GO_VERSION 1.7.5
ENV GO_VERSION 1.8.3
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash

View File

@ -11,7 +11,7 @@ RUN update-alternatives --install /usr/bin/go go /usr/lib/go-1.6/bin/go 100
# Install Go
# aarch64 doesn't have official go binaries, so use the version of go installed from
# the image to build go from source.
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash

View File

@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools bu
# Install Go
# aarch64 doesn't have official go binaries, so use the version of go installed from
# the image to build go from source.
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN mkdir /usr/src/go && curl -fsSL https://golang.org/dl/go${GO_VERSION}.src.tar.gz | tar -v -C /usr/src/go -xz --strip-components=1 \
&& cd /usr/src/go/src \
&& GOOS=linux GOARCH=arm64 GOROOT_BOOTSTRAP="$(go env GOROOT)" ./make.bash

View File

@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -12,7 +12,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list.d
RUN apt-get update && apt-get install -y -t wheezy-backports btrfs-tools --no-install-recommends && rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y apparmor bash-completion build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM ubuntu:trusty
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM ubuntu:xenial
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM ubuntu:yakkety
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM ubuntu:zesty
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.7.5
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
# GOARM is the ARM architecture version which is unrelated to the above Golang version
ENV GOARM 6
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local

View File

@ -6,7 +6,7 @@ FROM armhf/ubuntu:trusty
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM armhf/ubuntu:xenial
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM armhf/ubuntu:yakkety
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:trusty
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:xenial
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libseccomp-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:yakkety
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev pkg-config vim-common libseccomp-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM s390x/ubuntu:xenial
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config libsystemd-dev vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -6,7 +6,7 @@ FROM s390x/ubuntu:yakkety
RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libltdl-dev libseccomp-dev pkg-config libsystemd-dev vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/*
ENV GO_VERSION 1.7.5
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -7,7 +7,7 @@ FROM amazonlinux:latest
RUN yum groupinstall -y "Development Tools"
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common
ENV GO_VERSION 1.7.5
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -8,7 +8,7 @@ RUN yum groupinstall -y "Development Tools"
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -8,7 +8,7 @@ RUN dnf -y upgrade
RUN dnf install -y @development-tools fedora-packager
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -8,7 +8,7 @@ RUN dnf -y upgrade
RUN dnf install -y @development-tools fedora-packager
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -7,7 +7,7 @@ FROM opensuse:13.2
RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim systemd-rpm-macros
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -10,7 +10,7 @@ RUN yum install -y kernel-uek-devel-4.1.12-32.el6uek
RUN yum groupinstall -y "Development Tools"
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -7,7 +7,7 @@ FROM oraclelinux:7
RUN yum groupinstall -y "Development Tools"
RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -7,7 +7,7 @@ FROM photon:1.0
RUN tdnf install -y wget curl ca-certificates gzip make rpm-build sed gcc linux-api-headers glibc-devel binutils libseccomp libltdl-devel elfutils
RUN tdnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -9,7 +9,7 @@ RUN yum groupinstall --skip-broken -y "Development Tools"
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.7.4
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -0,0 +1,19 @@
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/ppc64le/generate.sh"!
#
FROM ppc64le/centos:7
RUN yum groupinstall -y "Development Tools"
RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs
RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
ENV AUTO_GOPATH 1
ENV DOCKER_BUILDTAGS pkcs11 seccomp selinux
ENV RUNC_BUILDTAGS seccomp selinux

View File

@ -8,7 +8,7 @@ RUN dnf -y upgrade
RUN dnf install -y @development-tools fedora-packager
RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake
ENV GO_VERSION 1.8.1
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin

View File

@ -4,8 +4,8 @@ set -e
# usage: ./generate.sh [versions]
# ie: ./generate.sh
# to update all Dockerfiles in this directory
# or: ./generate.sh
# to only update fedora-23/Dockerfile
# or: ./generate.sh centos-7
# to only update centos-7/Dockerfile
# or: ./generate.sh fedora-newversion
# to create a new folder and a Dockerfile within it
@ -20,8 +20,9 @@ versions=( "${versions[@]%/}" )
for version in "${versions[@]}"; do
distro="${version%-*}"
suite="${version##*-}"
from="${distro}:${suite}"
from="ppc64le/${distro}:${suite}"
installer=yum
if [[ "$distro" == "fedora" ]]; then
installer=dnf
fi
@ -33,7 +34,7 @@ for version in "${versions[@]}"; do
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/ppc64le/generate.sh"!
#
FROM ppc64le/$from
FROM $from
EOF
echo >> "$version/Dockerfile"
@ -42,14 +43,33 @@ for version in "${versions[@]}"; do
runcBuildTags=
case "$from" in
# add centos and opensuse tools install bits later
fedora:*)
ppc64le/fedora:*)
echo "RUN ${installer} -y upgrade" >> "$version/Dockerfile"
;;
*) ;;
esac
case "$from" in
ppc64le/centos:*)
# get "Development Tools" packages dependencies
echo 'RUN yum groupinstall -y "Development Tools"' >> "$version/Dockerfile"
if [[ "$version" == "centos-7" ]]; then
echo 'RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs' >> "$version/Dockerfile"
fi
;;
ppc64le/opensuse:*)
# Add the ppc64le repo (hopefully the image is updated soon)
# get rpm-build and curl packages and dependencies
echo "RUN zypper addrepo -n ppc64le-oss -f https://download.opensuse.org/ports/ppc/distribution/leap/${suite}/repo/oss/ ppc64le-oss" >> "$version/Dockerfile"
echo "RUN zypper addrepo -n ppc64le-updates -f https://download.opensuse.org/ports/update/${suite}/ ppc64le-updates" >> "$version/Dockerfile"
echo 'RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build' >> "$version/Dockerfile"
;;
*)
echo "RUN ${installer} install -y @development-tools fedora-packager" >> "$version/Dockerfile"
;;
esac
# this list is sorted alphabetically; please keep it that way
packages=(
btrfs-progs-devel # for "btrfs/ioctl.h" (and "version.h" if possible)
device-mapper-devel # for "libdevmapper.h"
@ -60,15 +80,20 @@ for version in "${versions[@]}"; do
pkgconfig # for the pkg-config command
selinux-policy
selinux-policy-devel
sqlite-devel # for "sqlite3.h"
systemd-devel # for "sd-journal.h" and libraries
tar # older versions of dev-tools do not have tar
git # required for containerd and runc clone
cmake # tini build
vim-common # tini build
)
# opensuse does not have the right libseccomp libs
case "$from" in
# add opensuse libseccomp package substitution when adding build support
ppc64le/opensuse:*)
packages=( "${packages[@]/libseccomp-devel}" )
runcBuildTags="selinux"
;;
*)
extraBuildTags+=' seccomp'
runcBuildTags="seccomp selinux"
@ -76,7 +101,17 @@ for version in "${versions[@]}"; do
esac
case "$from" in
# add opensuse btrfs package substitution when adding build support
ppc64le/opensuse:*)
packages=( "${packages[@]/btrfs-progs-devel/libbtrfs-devel}" )
packages=( "${packages[@]/pkgconfig/pkg-config}" )
packages=( "${packages[@]/vim-common/vim}" )
if [[ "$from" == "ppc64le/opensuse:13."* ]]; then
packages+=( systemd-rpm-macros )
fi
# use zypper
echo "RUN zypper --non-interactive install ${packages[*]}" >> "$version/Dockerfile"
;;
*)
echo "RUN ${installer} install -y ${packages[*]}" >> "$version/Dockerfile"
;;
@ -84,12 +119,15 @@ for version in "${versions[@]}"; do
echo >> "$version/Dockerfile"
awk '$1 == "ENV" && $2 == "GO_VERSION" { print; exit }' ../../../../Dockerfile.ppc64le >> "$version/Dockerfile"
echo 'RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local' >> "$version/Dockerfile"
echo 'ENV PATH $PATH:/usr/local/go/bin' >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
echo 'ENV AUTO_GOPATH 1' >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
# print build tags in alphabetical order

View File

@ -0,0 +1,20 @@
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/ppc64le/generate.sh"!
#
FROM ppc64le/opensuse:42.1
RUN zypper addrepo -n ppc64le-oss -f https://download.opensuse.org/ports/ppc/distribution/leap/42.1/repo/oss/ ppc64le-oss
RUN zypper addrepo -n ppc64le-updates -f https://download.opensuse.org/ports/update/42.1/ ppc64le-updates
RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim
ENV GO_VERSION 1.8.3
RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
ENV AUTO_GOPATH 1
ENV DOCKER_BUILDTAGS pkcs11 selinux
ENV RUNC_BUILDTAGS selinux

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
set -x
./generate.sh
for d in */; do
docker build -t "dockercore/builder-rpm:$(basename "$d")" "$d"
done

View File

@ -0,0 +1,19 @@
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/s390x/generate.sh"!
#
FROM sinenomine/clefos-base-s390x
RUN touch /var/lib/rpm/* && yum groupinstall -y "Development Tools"
RUN touch /var/lib/rpm/* && yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
ENV AUTO_GOPATH 1
ENV DOCKER_BUILDTAGS pkcs11 seccomp selinux
ENV RUNC_BUILDTAGS seccomp selinux
RUN ln -s /usr/bin/gcc /usr/bin/s390x-linux-gnu-gcc

View File

@ -0,0 +1,145 @@
#!/usr/bin/env bash
set -e
# This file is used to auto-generate Dockerfiles for making rpms via 'make rpm'
#
# usage: ./generate.sh [versions]
# ie: ./generate.sh
# to update all Dockerfiles in this directory
# or: ./generate.sh centos-7
# to only update centos-7/Dockerfile
# or: ./generate.sh fedora-newversion
# to create a new folder and a Dockerfile within it
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"
versions=( "$@" )
if [ ${#versions[@]} -eq 0 ]; then
versions=( */ )
fi
versions=( "${versions[@]%/}" )
for version in "${versions[@]}"; do
echo "${versions[@]}"
distro="${version%-*}"
suite="${version##*-}"
case "$distro" in
*opensuse*)
from="opensuse/s390x:tumbleweed"
;;
*clefos*)
from="sinenomine/${distro}"
;;
*)
echo No appropriate or supported image available.
exit 1
;;
esac
installer=yum
mkdir -p "$version"
echo "$version -> FROM $from"
cat > "$version/Dockerfile" <<-EOF
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/s390x/generate.sh"!
#
FROM $from
EOF
echo >> "$version/Dockerfile"
extraBuildTags='pkcs11'
runcBuildTags=
case "$from" in
*clefos*)
# Fix for RHBZ #1213602 + get "Development Tools" packages dependencies
echo 'RUN touch /var/lib/rpm/* && yum groupinstall -y "Development Tools"' >> "$version/Dockerfile"
;;
*opensuse*)
echo "RUN zypper ar https://download.opensuse.org/ports/zsystems/tumbleweed/repo/oss/ tumbleweed" >> "$version/Dockerfile"
# get rpm-build and curl packages and dependencies
echo 'RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build' >> "$version/Dockerfile"
;;
*)
echo No appropriate or supported image available.
exit 1
;;
esac
packages=(
btrfs-progs-devel # for "btrfs/ioctl.h" (and "version.h" if possible)
device-mapper-devel # for "libdevmapper.h"
glibc-static
libseccomp-devel # for "seccomp.h" & "libseccomp.so"
libselinux-devel # for "libselinux.so"
libtool-ltdl-devel # for pkcs11 "ltdl.h"
pkgconfig # for the pkg-config command
selinux-policy
selinux-policy-devel
sqlite-devel # for "sqlite3.h"
systemd-devel # for "sd-journal.h" and libraries
tar # older versions of dev-tools do not have tar
git # required for containerd and runc clone
cmake # tini build
vim-common # tini build
)
case "$from" in
*clefos*)
extraBuildTags+=' seccomp'
runcBuildTags="seccomp selinux"
;;
*opensuse*)
packages=( "${packages[@]/libseccomp-devel}" )
runcBuildTags="selinux"
;;
*)
echo No appropriate or supported image available.
exit 1
;;
esac
case "$from" in
*clefos*)
# Same RHBZ fix needed on all yum lines
echo "RUN touch /var/lib/rpm/* && ${installer} install -y ${packages[*]}" >> "$version/Dockerfile"
;;
*opensuse*)
packages=( "${packages[@]/btrfs-progs-devel/libbtrfs-devel}" )
packages=( "${packages[@]/pkgconfig/pkg-config}" )
packages=( "${packages[@]/vim-common/vim}" )
packages+=( systemd-rpm-macros ) # for use of >= opensuse:13.*
# use zypper
echo "RUN zypper --non-interactive install ${packages[*]}" >> "$version/Dockerfile"
;;
*)
echo No appropriate or supported image available.
exit 1
;;
esac
echo >> "$version/Dockerfile"
awk '$1 == "ENV" && $2 == "GO_VERSION" { print; exit }' ../../../../Dockerfile.s390x >> "$version/Dockerfile"
echo 'RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local' >> "$version/Dockerfile"
echo 'ENV PATH $PATH:/usr/local/go/bin' >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
echo 'ENV AUTO_GOPATH 1' >> "$version/Dockerfile"
echo >> "$version/Dockerfile"
# print build tags in alphabetical order
buildTags=$( echo "selinux $extraBuildTags" | xargs -n1 | sort -n | tr '\n' ' ' | sed -e 's/[[:space:]]*$//' )
echo "ENV DOCKER_BUILDTAGS $buildTags" >> "$version/Dockerfile"
echo "ENV RUNC_BUILDTAGS $runcBuildTags" >> "$version/Dockerfile"
# TODO: Investigate why "s390x-linux-gnu-gcc" is required
echo "RUN ln -s /usr/bin/gcc /usr/bin/s390x-linux-gnu-gcc" >> "$version/Dockerfile"
done

View File

@ -0,0 +1,20 @@
#
# THIS FILE IS AUTOGENERATED; SEE "contrib/builder/rpm/s390x/generate.sh"!
#
FROM opensuse/s390x:tumbleweed
RUN zypper ar https://download.opensuse.org/ports/zsystems/tumbleweed/repo/oss/ tumbleweed
RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build
RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim systemd-rpm-macros
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local
ENV PATH $PATH:/usr/local/go/bin
ENV AUTO_GOPATH 1
ENV DOCKER_BUILDTAGS pkcs11 selinux
ENV RUNC_BUILDTAGS selinux
RUN ln -s /usr/bin/gcc /usr/bin/s390x-linux-gnu-gcc

View File

@ -157,6 +157,7 @@ while [ $# -gt 0 ]; do
echo "skipping existing ${layerId:0:12}"
continue
fi
token="$(curl -fsSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull" | jq --raw-output '.token')"
curl -fSL --progress \
-H "Authorization: Bearer $token" \
"https://registry-1.docker.io/v2/$image/blobs/$layerDigest" \
@ -229,6 +230,7 @@ while [ $# -gt 0 ]; do
echo "skipping existing ${layerId:0:12}"
continue
fi
token="$(curl -fsSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull" | jq --raw-output '.token')"
curl -fSL --progress -H "Authorization: Bearer $token" "https://registry-1.docker.io/v2/$image/blobs/$imageLayer" -o "$dir/$layerId/layer.tar" # -C -
done
;;

View File

@ -10,6 +10,23 @@
<string>Dockerfile</string>
<key>patterns</key>
<array>
<dict>
<key>captures</key>
<dict>
<key>1</key>
<dict>
<key>name</key>
<string>keyword.other.special-method.dockerfile</string>
</dict>
<key>2</key>
<dict>
<key>name</key>
<string>keyword.other.special-method.dockerfile</string>
</dict>
</dict>
<key>match</key>
<string>^\s*\b(FROM)\b.*?\b(AS)\b</string>
</dict>
<dict>
<key>captures</key>
<dict>

View File

@ -31,7 +31,11 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA
return err
}
if container.IsPaused() {
err := fmt.Errorf("Container %s is paused. Unpause the container before attach", prefixOrName)
err := fmt.Errorf("Container %s is paused, unpause the container before attach.", prefixOrName)
return errors.NewRequestConflictError(err)
}
if container.IsRestarting() {
err := fmt.Errorf("Container %s is restarting, wait until the container is running.", prefixOrName)
return errors.NewRequestConflictError(err)
}

View File

@ -36,9 +36,9 @@ func networkFromGRPC(n *swarmapi.Network) types.Network {
IPAMOptions: ipamFromGRPC(n.IPAM),
}
if n.Spec.ConfigFrom != "" {
if n.Spec.GetNetwork() != "" {
network.Spec.ConfigFrom = &networktypes.ConfigReference{
Network: n.Spec.ConfigFrom,
Network: n.Spec.GetNetwork(),
}
}
@ -169,9 +169,9 @@ func BasicNetworkFromGRPC(n swarmapi.Network) basictypes.NetworkResource {
Labels: n.Spec.Annotations.Labels,
}
if n.Spec.ConfigFrom != "" {
if n.Spec.GetNetwork() != "" {
nr.ConfigFrom = networktypes.ConfigReference{
Network: n.Spec.ConfigFrom,
Network: n.Spec.GetNetwork(),
}
}
@ -221,7 +221,9 @@ func BasicNetworkCreateToGRPC(create basictypes.NetworkCreateRequest) swarmapi.N
ns.IPAM.Configs = ipamSpec
}
if create.ConfigFrom != nil {
ns.ConfigFrom = create.ConfigFrom.Network
ns.ConfigFrom = &swarmapi.NetworkSpec_Network{
Network: create.ConfigFrom.Network,
}
}
return ns
}

View File

@ -100,7 +100,6 @@ func serviceSpecFromGRPC(spec *swarmapi.ServiceSpec) (*types.ServiceSpec, error)
return nil, fmt.Errorf("unknown task runtime type: %s", t.Generic.Payload.TypeUrl)
}
taskTemplate.RuntimeData = t.Generic.Payload.Value
default:
return nil, fmt.Errorf("error creating service; unsupported runtime %T", t)
}
@ -176,7 +175,6 @@ func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) {
Kind: string(types.RuntimePlugin),
Payload: &gogotypes.Any{
TypeUrl: string(types.RuntimeURLPlugin),
Value: s.TaskTemplate.RuntimeData,
},
},
}

View File

@ -597,9 +597,9 @@ func (c *containerConfig) networkCreateRequest(name string) (clustertypes.Networ
Scope: netconst.SwarmScope,
}
if na.Network.Spec.ConfigFrom != "" {
if na.Network.Spec.GetNetwork() != "" {
options.ConfigFrom = &network.ConfigReference{
Network: na.Network.Spec.ConfigFrom,
Network: na.Network.Spec.GetNetwork(),
}
}

View File

@ -88,10 +88,6 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
}
}
if !req.ForceNewCluster {
clearPersistentState(c.root)
}
nr, err := c.newNodeRunner(nodeStartConfig{
forceNewCluster: req.ForceNewCluster,
autolock: req.AutoLockManagers,
@ -109,16 +105,14 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
c.mu.Unlock()
if err := <-nr.Ready(); err != nil {
c.mu.Lock()
c.nr = nil
c.mu.Unlock()
if !req.ForceNewCluster { // if failure on first attempt don't keep state
if err := clearPersistentState(c.root); err != nil {
return "", err
}
}
if err != nil {
c.mu.Lock()
c.nr = nil
c.mu.Unlock()
}
return "", err
}
state := nr.State()
@ -166,8 +160,6 @@ func (c *Cluster) Join(req types.JoinRequest) error {
return err
}
clearPersistentState(c.root)
nr, err := c.newNodeRunner(nodeStartConfig{
RemoteAddr: req.RemoteAddrs[0],
ListenAddr: net.JoinHostPort(listenHost, listenPort),
@ -193,6 +185,9 @@ func (c *Cluster) Join(req types.JoinRequest) error {
c.mu.Lock()
c.nr = nil
c.mu.Unlock()
if err := clearPersistentState(c.root); err != nil {
return err
}
}
return err
}

View File

@ -64,31 +64,35 @@ type cmdProbe struct {
// exec the healthcheck command in the container.
// Returns the exit code and probe output (if any)
func (p *cmdProbe) run(ctx context.Context, d *Daemon, container *container.Container) (*types.HealthcheckResult, error) {
cmdSlice := strslice.StrSlice(container.Config.Healthcheck.Test)[1:]
func (p *cmdProbe) run(ctx context.Context, d *Daemon, cntr *container.Container) (*types.HealthcheckResult, error) {
cmdSlice := strslice.StrSlice(cntr.Config.Healthcheck.Test)[1:]
if p.shell {
cmdSlice = append(getShell(container.Config), cmdSlice...)
cmdSlice = append(getShell(cntr.Config), cmdSlice...)
}
entrypoint, args := d.getEntrypointAndArgs(strslice.StrSlice{}, cmdSlice)
execConfig := exec.NewConfig()
execConfig.OpenStdin = false
execConfig.OpenStdout = true
execConfig.OpenStderr = true
execConfig.ContainerID = container.ID
execConfig.ContainerID = cntr.ID
execConfig.DetachKeys = []byte{}
execConfig.Entrypoint = entrypoint
execConfig.Args = args
execConfig.Tty = false
execConfig.Privileged = false
execConfig.User = container.Config.User
execConfig.Env = container.Config.Env
execConfig.User = cntr.Config.User
d.registerExecCommand(container, execConfig)
d.LogContainerEvent(container, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "))
linkedEnv, err := d.setupLinkedContainers(cntr)
if err != nil {
return nil, err
}
execConfig.Env = container.ReplaceOrAppendEnvValues(cntr.CreateDaemonEnvironment(execConfig.Tty, linkedEnv), execConfig.Env)
d.registerExecCommand(cntr, execConfig)
d.LogContainerEvent(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "))
output := &limitedBuffer{}
err := d.ContainerExecStart(ctx, execConfig.ID, nil, output, output)
err = d.ContainerExecStart(ctx, execConfig.ID, nil, output, output)
if err != nil {
return nil, err
}
@ -97,7 +101,7 @@ func (p *cmdProbe) run(ctx context.Context, d *Daemon, container *container.Cont
return nil, err
}
if info.ExitCode == nil {
return nil, fmt.Errorf("Healthcheck for container %s has no exit code!", container.ID)
return nil, fmt.Errorf("Healthcheck for container %s has no exit code!", cntr.ID)
}
// Note: Go's json package will handle invalid UTF-8 for us
out := output.String()

View File

@ -1,6 +1,7 @@
package loggerutils
import (
"errors"
"os"
"strconv"
"sync"
@ -11,6 +12,7 @@ import (
// RotateFileWriter is Logger implementation for default Docker logging.
type RotateFileWriter struct {
f *os.File // store for closing
closed bool
mu sync.Mutex
capacity int64 //maximum size of each file
currentSize int64 // current size of the latest file
@ -42,6 +44,10 @@ func NewRotateFileWriter(logPath string, capacity int64, maxFiles int) (*RotateF
//WriteLog write log message to File
func (w *RotateFileWriter) Write(message []byte) (int, error) {
w.mu.Lock()
if w.closed {
w.mu.Unlock()
return -1, errors.New("cannot write because the output file was closed")
}
if err := w.checkCapacityAndRotate(); err != nil {
w.mu.Unlock()
return -1, err
@ -100,6 +106,8 @@ func rotate(name string, maxFiles int) error {
// LogPath returns the location the given writer logs to.
func (w *RotateFileWriter) LogPath() string {
w.mu.Lock()
defer w.mu.Unlock()
return w.f.Name()
}
@ -120,5 +128,14 @@ func (w *RotateFileWriter) NotifyRotateEvict(sub chan interface{}) {
// Close closes underlying file and signals all readers to stop.
func (w *RotateFileWriter) Close() error {
return w.f.Close()
w.mu.Lock()
defer w.mu.Unlock()
if w.closed {
return nil
}
if err := w.f.Close(); err != nil {
return err
}
w.closed = true
return nil
}

View File

@ -120,7 +120,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
// In s.Windows.Resources
cpuShares := uint16(c.HostConfig.CPUShares)
cpuPercent := uint8(c.HostConfig.CPUPercent)
cpuMaximum := uint16(c.HostConfig.CPUPercent) * 100
cpuCount := uint64(c.HostConfig.CPUCount)
if c.HostConfig.NanoCPUs > 0 {
if isHyperV {
@ -128,21 +128,24 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
leftoverNanoCPUs := c.HostConfig.NanoCPUs % 1e9
if leftoverNanoCPUs != 0 {
cpuCount++
cpuPercent = uint8(c.HostConfig.NanoCPUs * 100 / int64(cpuCount) / 1e9)
cpuMaximum = uint16(c.HostConfig.NanoCPUs / int64(cpuCount) / (1e9 / 10000))
if cpuMaximum < 1 {
// The requested NanoCPUs is so small that we rounded to 0, use 1 instead
cpuMaximum = 1
}
}
} else {
cpuPercent = uint8(c.HostConfig.NanoCPUs * 100 / int64(sysinfo.NumCPU()) / 1e9)
if cpuPercent < 1 {
cpuMaximum = uint16(c.HostConfig.NanoCPUs / int64(sysinfo.NumCPU()) / (1e9 / 10000))
if cpuMaximum < 1 {
// The requested NanoCPUs is so small that we rounded to 0, use 1 instead
cpuPercent = 1
cpuMaximum = 1
}
}
}
memoryLimit := uint64(c.HostConfig.Memory)
s.Windows.Resources = &specs.WindowsResources{
CPU: &specs.WindowsCPUResources{
Percent: &cpuPercent,
Maximum: &cpuMaximum,
Shares: &cpuShares,
Count: &cpuCount,
},

View File

@ -216,7 +216,7 @@ func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args
if !until.IsZero() && img.Created.After(until) {
continue
}
if !matchLabels(pruneFilters, img.Config.Labels) {
if img.Config != nil && !matchLabels(pruneFilters, img.Config.Labels) {
continue
}
topImages[id] = img

View File

@ -9,7 +9,6 @@ import (
"github.com/docker/docker/container"
"github.com/docker/docker/layer"
"github.com/docker/docker/libcontainerd"
"github.com/docker/docker/pkg/system"
"golang.org/x/sys/windows/registry"
)
@ -32,12 +31,6 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
}
dnsSearch := daemon.getDNSSearchSettings(container)
if dnsSearch != nil {
osv := system.GetOSVersion()
if osv.Build < 14997 {
return nil, fmt.Errorf("dns-search option is not supported on the current platform")
}
}
// Generate the layer folder of the layer options
layerOpts := &libcontainerd.LayerOption{}
@ -45,10 +38,6 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
if err != nil {
return nil, fmt.Errorf("failed to get layer metadata - %s", err)
}
if hvOpts.IsHyperV {
hvOpts.SandboxPath = filepath.Dir(m["dir"])
}
layerOpts.LayerFolderPath = m["dir"]
// Generate the layer paths of the layer options

View File

@ -7,6 +7,7 @@ import (
"path/filepath"
"reflect"
"strings"
"time"
"github.com/Sirupsen/logrus"
dockererrors "github.com/docker/docker/api/errors"
@ -28,9 +29,11 @@ type mounts []container.Mount
// volumeToAPIType converts a volume.Volume to the type used by the Engine API
func volumeToAPIType(v volume.Volume) *types.Volume {
createdAt, _ := v.CreatedAt()
tv := &types.Volume{
Name: v.Name(),
Driver: v.DriverName(),
Name: v.Name(),
Driver: v.DriverName(),
CreatedAt: createdAt.Format(time.RFC3339),
}
if v, ok := v.(volume.DetailedVolume); ok {
tv.Labels = v.Labels()

View File

@ -12,7 +12,7 @@ import (
"testing"
"github.com/docker/docker/api/types/swarm"
dcli "github.com/docker/docker/cli"
"github.com/docker/docker/cli/flags"
"github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/integration-cli/cli/build/fakestorage"
"github.com/docker/docker/integration-cli/daemon"
@ -406,7 +406,7 @@ func (s *DockerTrustSuite) TearDownTest(c *check.C) {
}
// Remove trusted keys and metadata after test
os.RemoveAll(filepath.Join(dcli.ConfigurationDir(), "trust"))
os.RemoveAll(filepath.Join(flags.ConfigurationDir(), "trust"))
s.ds.TearDownTest(c)
}

View File

@ -2,8 +2,11 @@ package main
import (
"encoding/json"
"fmt"
"net/http"
"path/filepath"
"strings"
"time"
"github.com/docker/docker/api/types"
volumetypes "github.com/docker/docker/api/types/volume"
@ -69,6 +72,8 @@ func (s *DockerSuite) TestVolumesAPIInspect(c *check.C) {
config := volumetypes.VolumesCreateBody{
Name: "test",
}
// sampling current time minus a minute so to now have false positive in case of delays
now := time.Now().Truncate(time.Minute)
status, b, err := request.SockRequest("POST", "/volumes/create", config, daemonHost())
c.Assert(err, check.IsNil)
c.Assert(status, check.Equals, http.StatusCreated, check.Commentf(string(b)))
@ -87,4 +92,12 @@ func (s *DockerSuite) TestVolumesAPIInspect(c *check.C) {
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf(string(b)))
c.Assert(json.Unmarshal(b, &vol), checker.IsNil)
c.Assert(vol.Name, checker.Equals, config.Name)
// comparing CreatedAt field time for the new volume to now. Removing a minute from both to avoid false positive
testCreatedAt, err := time.Parse(time.RFC3339, strings.TrimSpace(vol.CreatedAt))
c.Assert(err, check.IsNil)
testCreatedAt = testCreatedAt.Truncate(time.Minute)
if !testCreatedAt.Equal(now) {
c.Assert(fmt.Errorf("Time Volume is CreatedAt not equal to current time"), check.NotNil)
}
}

View File

@ -139,3 +139,26 @@ func (s *DockerSuite) TestHealth(c *check.C) {
c.Check(out, checker.Equals, "[CMD cat /my status]\n")
}
// Github #33021
func (s *DockerSuite) TestUnsetEnvVarHealthCheck(c *check.C) {
testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows
imageName := "testhealth"
buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
HEALTHCHECK --interval=1s --timeout=5s --retries=5 CMD /bin/sh -c "sleep 1"
ENTRYPOINT /bin/sh -c "sleep 600"`))
name := "env_test_health"
// No health status before starting
dockerCmd(c, "run", "-d", "--name", name, "-e", "FOO", imageName)
defer func() {
dockerCmd(c, "rm", "-f", name)
dockerCmd(c, "rmi", imageName)
}()
// Start
dockerCmd(c, "start", name)
waitForHealthStatus(c, name, "starting", "healthy")
}

View File

@ -100,7 +100,7 @@ func (s *DockerSuite) TestImagesFilterLabelMatch(c *check.C) {
}
// Regression : #15659
func (s *DockerSuite) TestImagesFilterLabelWithCommit(c *check.C) {
func (s *DockerSuite) TestCommitWithFilterLabel(c *check.C) {
// Create a container
dockerCmd(c, "run", "--name", "bar", "busybox", "/bin/sh")
// Commit with labels "using changes"

View File

@ -44,7 +44,7 @@ func (s *DockerSuite) TestNetHostname(c *check.C) {
c.Assert(out, checker.Contains, runconfig.ErrConflictNetworkHostname.Error())
out, _ = dockerCmdWithFail(c, "run", "--net=container", "busybox", "ps")
c.Assert(out, checker.Contains, "--net: invalid net mode: invalid container format container:<name|id>")
c.Assert(out, checker.Contains, "Invalid network mode: invalid container format container:<name|id>")
out, _ = dockerCmdWithFail(c, "run", "--net=weird", "busybox", "ps")
c.Assert(out, checker.Contains, "network weird not found")

View File

@ -12,7 +12,7 @@ import (
"sync"
"github.com/docker/distribution/reference"
dcli "github.com/docker/docker/cli"
"github.com/docker/docker/cli/flags"
"github.com/docker/docker/integration-cli/checker"
"github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/integration-cli/cli/build"
@ -294,7 +294,7 @@ func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
})
// Assert that we rotated the snapshot key to the server by checking our local keystore
contents, err := ioutil.ReadDir(filepath.Join(dcli.ConfigurationDir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest"))
contents, err := ioutil.ReadDir(filepath.Join(flags.ConfigurationDir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest"))
c.Assert(err, check.IsNil, check.Commentf("Unable to read local tuf key files"))
// Check that we only have 1 key (targets key)
c.Assert(contents, checker.HasLen, 1)
@ -399,7 +399,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C)
s.assertTargetNotInRoles(c, repoName, "latest", "targets")
// Try pull after push
os.RemoveAll(filepath.Join(dcli.ConfigurationDir(), "trust"))
os.RemoveAll(filepath.Join(flags.ConfigurationDir(), "trust"))
cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{
Out: "Status: Image is up to date",
@ -436,7 +436,7 @@ func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c
s.assertTargetNotInRoles(c, repoName, "latest", "targets")
// Try pull after push
os.RemoveAll(filepath.Join(dcli.ConfigurationDir(), "trust"))
os.RemoveAll(filepath.Join(flags.ConfigurationDir(), "trust"))
// pull should fail because none of these are the releases role
cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{
@ -472,7 +472,7 @@ func (s *DockerTrustSuite) TestTrustedPushSignsForRolesWithKeysAndValidPaths(c *
s.assertTargetNotInRoles(c, repoName, "latest", "targets")
// Try pull after push
os.RemoveAll(filepath.Join(dcli.ConfigurationDir(), "trust"))
os.RemoveAll(filepath.Join(flags.ConfigurationDir(), "trust"))
// pull should fail because none of these are the releases role
cli.Docker(cli.Args("pull", targetName), trustedCmd).Assert(c, icmd.Expected{

View File

@ -448,7 +448,7 @@ func (s *DockerSwarmSuite) TestOverlayAttachableReleaseResourcesOnFailure(c *che
out, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c1", "--ip", "10.10.9.33", "busybox", "top")
c.Assert(err, checker.IsNil, check.Commentf(out))
// Attempt to attach another contianer with same IP, must fail
// Attempt to attach another container with same IP, must fail
_, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c2", "--ip", "10.10.9.33", "busybox", "top")
c.Assert(err, checker.NotNil)
@ -2002,6 +2002,35 @@ func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *check.C) {
}
}
const defaultRetryCount = 10
func waitForEvent(c *check.C, d *daemon.Swarm, since string, filter string, event string, retry int) string {
if retry < 1 {
c.Fatalf("retry count %d is invalid. It should be no less than 1", retry)
return ""
}
var out string
for i := 0; i < retry; i++ {
until := daemonUnixTime(c)
var err error
if len(filter) > 0 {
out, err = d.Cmd("events", "--since", since, "--until", until, filter)
} else {
out, err = d.Cmd("events", "--since", since, "--until", until)
}
c.Assert(err, checker.IsNil, check.Commentf(out))
if strings.Contains(out, event) {
return strings.TrimSpace(out)
}
// no need to sleep after last retry
if i < retry-1 {
time.Sleep(200 * time.Millisecond)
}
}
c.Fatalf("docker events output '%s' doesn't contain event '%s'", out, event)
return ""
}
func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *check.C) {
d1 := s.AddDaemon(c, true, true)
d2 := s.AddDaemon(c, true, true)
@ -2013,21 +2042,13 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *check.C) {
networkID := strings.TrimSpace(out)
c.Assert(networkID, checker.Not(checker.Equals), "")
until := daemonUnixTime(c)
// d1 is a manager
out, err = d1.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Contains, "network create "+networkID)
// d2 is a manager
out, err = d2.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Contains, "network create "+networkID)
// d1, d2 are managers that can get swarm events
waitForEvent(c, d1, "0", "-f scope=swarm", "network create "+networkID, defaultRetryCount)
waitForEvent(c, d2, "0", "-f scope=swarm", "network create "+networkID, defaultRetryCount)
// d3 is a worker, not able to get cluster events
out, err = d3.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), "network create ")
out = waitForEvent(c, d3, "0", "-f scope=swarm", "", 1)
c.Assert(out, checker.Not(checker.Contains), "network create ")
}
func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *check.C) {
@ -2038,24 +2059,17 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *check.C) {
c.Assert(err, checker.IsNil, check.Commentf(out))
serviceID := strings.Split(out, "\n")[0]
until := daemonUnixTime(c)
// scope swarm filters cluster events
out, err = d.Cmd("events", "--since=0", "--until", until, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Contains, "service create "+serviceID)
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), "container create ")
out = waitForEvent(c, d, "0", "-f scope=swarm", "service create "+serviceID, defaultRetryCount)
c.Assert(out, checker.Not(checker.Contains), "container create ")
// without scope all events are returned
out, err = d.Cmd("events", "--since=0", "--until", until)
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Contains, "service create "+serviceID)
c.Assert(strings.TrimSpace(out), checker.Contains, "container create ")
// all events are returned if scope is not specified
waitForEvent(c, d, "0", "", "service create "+serviceID, 1)
waitForEvent(c, d, "0", "", "container create ", defaultRetryCount)
// scope local only show non-cluster events
out, err = d.Cmd("events", "--since=0", "--until", until, "-f scope=local")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), "service create ")
c.Assert(strings.TrimSpace(out), checker.Contains, "container create ")
// scope local only shows non-cluster events
out = waitForEvent(c, d, "0", "-f scope=local", "container create ", 1)
c.Assert(out, checker.Not(checker.Contains), "service create ")
}
func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *check.C) {
@ -2072,17 +2086,12 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *check.C) {
networkID := strings.TrimSpace(out)
c.Assert(networkID, checker.Not(checker.Equals), "")
until := daemonUnixTime(c)
// filter by service
out, err = d.Cmd("events", "--since=0", "--until", until, "-f type=service")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "service create "+serviceID)
out = waitForEvent(c, d, "0", "-f type=service", "service create "+serviceID, defaultRetryCount)
c.Assert(out, checker.Not(checker.Contains), "network create")
// filter by network
out, err = d.Cmd("events", "--since=0", "--until", until, "-f type=network")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "network create "+networkID)
out = waitForEvent(c, d, "0", "-f type=network", "network create "+networkID, defaultRetryCount)
c.Assert(out, checker.Not(checker.Contains), "service create")
}
@ -2094,40 +2103,36 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsService(c *check.C) {
c.Assert(err, checker.IsNil, check.Commentf(out))
serviceID := strings.Split(out, "\n")[0]
t1 := daemonUnixTime(c)
// validate service create event
out, err = d.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "service create "+serviceID)
waitForEvent(c, d, "0", "-f scope=swarm", "service create "+serviceID, defaultRetryCount)
t1 := daemonUnixTime(c)
out, err = d.Cmd("service", "update", "--force", "--detach=false", "test")
c.Assert(err, checker.IsNil, check.Commentf(out))
t2 := daemonUnixTime(c)
out, err = d.Cmd("events", "--since", t1, "--until", t2, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "service update "+serviceID)
// wait for service update start
out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceID, defaultRetryCount)
c.Assert(out, checker.Contains, "updatestate.new=updating")
// allow service update complete. This is a service with 1 instance
time.Sleep(400 * time.Millisecond)
out = waitForEvent(c, d, t1, "-f scope=swarm", "service update "+serviceID, defaultRetryCount)
c.Assert(out, checker.Contains, "updatestate.new=completed, updatestate.old=updating")
// scale service
t2 := daemonUnixTime(c)
out, err = d.Cmd("service", "scale", "test=3")
c.Assert(err, checker.IsNil, check.Commentf(out))
t3 := daemonUnixTime(c)
out, err = d.Cmd("events", "--since", t2, "--until", t3, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "service update "+serviceID)
out = waitForEvent(c, d, t2, "-f scope=swarm", "service update "+serviceID, defaultRetryCount)
c.Assert(out, checker.Contains, "replicas.new=3, replicas.old=1")
// remove service
t3 := daemonUnixTime(c)
out, err = d.Cmd("service", "rm", "test")
c.Assert(err, checker.IsNil, check.Commentf(out))
t4 := daemonUnixTime(c)
out, err = d.Cmd("events", "--since", t3, "--until", t4, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "service remove "+serviceID)
waitForEvent(c, d, t3, "-f scope=swarm", "service remove "+serviceID, defaultRetryCount)
}
func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *check.C) {
@ -2136,38 +2141,28 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *check.C) {
d3 := s.AddDaemon(c, true, true)
d3ID := d3.NodeID
waitForEvent(c, d1, "0", "-f scope=swarm", "node create "+d3ID, defaultRetryCount)
t1 := daemonUnixTime(c)
out, err := d1.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "node create "+d3ID)
out, err = d1.Cmd("node", "update", "--availability=pause", d3ID)
out, err := d1.Cmd("node", "update", "--availability=pause", d3ID)
c.Assert(err, checker.IsNil, check.Commentf(out))
t2 := daemonUnixTime(c)
// filter by type
out, err = d1.Cmd("events", "--since", t1, "--until", t2, "-f type=node")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "node update "+d3ID)
out = waitForEvent(c, d1, t1, "-f type=node", "node update "+d3ID, defaultRetryCount)
c.Assert(out, checker.Contains, "availability.new=pause, availability.old=active")
t2 := daemonUnixTime(c)
out, err = d1.Cmd("node", "demote", d3ID)
c.Assert(err, checker.IsNil, check.Commentf(out))
t3 := daemonUnixTime(c)
// filter by type and scope
out, err = d1.Cmd("events", "--since", t2, "--until", t3, "-f type=node", "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "node update "+d3ID)
waitForEvent(c, d1, t2, "-f type=node", "node update "+d3ID, defaultRetryCount)
t3 := daemonUnixTime(c)
out, err = d1.Cmd("node", "rm", "-f", d3ID)
c.Assert(err, checker.IsNil, check.Commentf(out))
t4 := daemonUnixTime(c)
// filter by type and scope
out, err = d1.Cmd("events", "--since", t3, "--until", t4, "-f type=node", "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "node remove "+d3ID)
// filter by scope
waitForEvent(c, d1, t3, "-f scope=swarm", "node remove "+d3ID, defaultRetryCount)
}
func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *check.C) {
@ -2178,20 +2173,15 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *check.C) {
c.Assert(err, checker.IsNil, check.Commentf(out))
networkID := strings.TrimSpace(out)
t1 := daemonUnixTime(c)
out, err = d.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "network create "+networkID)
waitForEvent(c, d, "0", "-f scope=swarm", "network create "+networkID, defaultRetryCount)
// remove network
t1 := daemonUnixTime(c)
out, err = d.Cmd("network", "rm", "foo")
c.Assert(err, checker.IsNil, check.Commentf(out))
t2 := daemonUnixTime(c)
// filtered by network
out, err = d.Cmd("events", "--since", t1, "--until", t2, "-f type=network")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "network remove "+networkID)
waitForEvent(c, d, t1, "-f type=network", "network remove "+networkID, defaultRetryCount)
}
func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *check.C) {
@ -2206,15 +2196,10 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *check.C) {
})
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
t1 := daemonUnixTime(c)
out, err := d.Cmd("events", "--since=0", "--until", t1, "-f scope=swarm")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "secret create "+id)
waitForEvent(c, d, "0", "-f scope=swarm", "secret create "+id, defaultRetryCount)
t1 := daemonUnixTime(c)
d.DeleteSecret(c, id)
t2 := daemonUnixTime(c)
// filtered by secret
out, err = d.Cmd("events", "--since", t1, "--until", t2, "-f type=secret")
c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(out, checker.Contains, "secret remove "+id)
waitForEvent(c, d, t1, "-f type=secret", "secret remove "+id, defaultRetryCount)
}

View File

@ -217,13 +217,14 @@ func SockRequestRaw(method, endpoint string, data io.Reader, ct, daemon string,
}
resp, err := client.Do(req)
if err != nil {
client.Close()
return resp, nil, err
}
body := ioutils.NewReadCloserWrapper(resp.Body, func() error {
defer resp.Body.Close()
return client.Close()
})
if err != nil {
client.Close()
}
return resp, body, err
}

View File

@ -11,7 +11,7 @@ import (
"strings"
"time"
dcli "github.com/docker/docker/cli"
"github.com/docker/docker/cli/flags"
"github.com/docker/docker/integration-cli/checker"
"github.com/docker/docker/integration-cli/cli"
icmd "github.com/docker/docker/pkg/testutil/cmd"
@ -108,7 +108,7 @@ func newTestNotary(c *check.C) (*testNotary, error) {
"skipTLSVerify": true
}
}`
if _, err = fmt.Fprintf(clientConfig, template, filepath.Join(dcli.ConfigurationDir(), "trust"), notaryURL); err != nil {
if _, err = fmt.Fprintf(clientConfig, template, filepath.Join(flags.ConfigurationDir(), "trust"), notaryURL); err != nil {
os.RemoveAll(tmp)
return nil, err
}

View File

@ -49,7 +49,6 @@ const defaultOwner = "docker"
// | VolumePath | \\?\\Volume{GUIDa} | |
// | LayerFolderPath | %root%\windowsfilter\containerID | %root%\windowsfilter\containerID (servicing only) |
// | Layers[] | ID=GUIDb;Path=%root%\windowsfilter\layerID | ID=GUIDb;Path=%root%\windowsfilter\layerID |
// | SandboxPath | | %root%\windowsfilter |
// | HvRuntime | | ImagePath=%root%\BaseLayerID\UtilityVM |
// +-----------------+--------------------------------------------+---------------------------------------------------+
//
@ -88,7 +87,6 @@ const defaultOwner = "docker"
// }],
// "HostName": "475c2c58933b",
// "MappedDirectories": [],
// "SandboxPath": "C:\\\\control\\\\windowsfilter",
// "HvPartition": true,
// "EndpointList": ["e1bb1e61-d56f-405e-b75d-fd520cefa0cb"],
// "DNSSearchList": "a.com,b.com,c.com",
@ -128,8 +126,8 @@ func (clnt *client) Create(containerID string, checkpoint string, checkpointDir
if spec.Windows.Resources.CPU.Shares != nil {
configuration.ProcessorWeight = uint64(*spec.Windows.Resources.CPU.Shares)
}
if spec.Windows.Resources.CPU.Percent != nil {
configuration.ProcessorMaximum = int64(*spec.Windows.Resources.CPU.Percent) * 100 // ProcessorMaximum is a value between 1 and 10000
if spec.Windows.Resources.CPU.Maximum != nil {
configuration.ProcessorMaximum = int64(*spec.Windows.Resources.CPU.Maximum)
}
}
if spec.Windows.Resources.Memory != nil {
@ -159,7 +157,6 @@ func (clnt *client) Create(containerID string, checkpoint string, checkpointDir
}
if h, ok := option.(*HyperVIsolationOption); ok {
configuration.HvPartition = h.IsHyperV
configuration.SandboxPath = h.SandboxPath
continue
}
if l, ok := option.(*LayerOption); ok {

View File

@ -49,7 +49,7 @@ type remote struct {
stateDir string
rpcAddr string
startDaemon bool
closeManually bool
closedManually bool
debugLog bool
rpcConn *grpc.ClientConn
clients []*client
@ -154,7 +154,7 @@ func (r *remote) handleConnectionChange() {
logrus.Debugf("libcontainerd: containerd health check returned error: %v", err)
if r.daemonPid != -1 {
if r.closeManually {
if r.closedManually {
// Well, we asked for it to stop, just return
return
}
@ -180,7 +180,7 @@ func (r *remote) Cleanup() {
if r.daemonPid == -1 {
return
}
r.closeManually = true
r.closedManually = true
r.rpcConn.Close()
// Ask the daemon to quit
syscall.Kill(r.daemonPid, syscall.SIGTERM)
@ -280,10 +280,23 @@ func (r *remote) startEventsMonitor() error {
er := &containerd.EventsRequest{
Timestamp: tsp,
}
events, err := r.apiClient.Events(context.Background(), er, grpc.FailFast(false))
if err != nil {
return err
var events containerd.API_EventsClient
for {
events, err = r.apiClient.Events(context.Background(), er, grpc.FailFast(false))
if err == nil {
break
}
logrus.Warnf("libcontainerd: failed to get events from containerd: %q", err)
if r.closedManually {
// ignore error if grpc remote connection is closed manually
return nil
}
<-time.After(100 * time.Millisecond)
}
go r.handleEventStream(events)
return nil
}
@ -293,7 +306,7 @@ func (r *remote) handleEventStream(events containerd.API_EventsClient) {
e, err := events.Recv()
if err != nil {
if grpc.ErrorDesc(err) == transport.ErrConnClosing.Desc &&
r.closeManually {
r.closedManually {
// ignore error if grpc remote connection is closed manually
return
}
@ -414,6 +427,18 @@ func (r *remote) runContainerdDaemon() error {
if err := cmd.Start(); err != nil {
return err
}
// unless strictly necessary, do not add anything in between here
// as the reaper goroutine below needs to kick in as soon as possible
// and any "return" from code paths added here will defeat the reaper
// process.
r.daemonWaitCh = make(chan struct{})
go func() {
cmd.Wait()
close(r.daemonWaitCh)
}() // Reap our child when needed
logrus.Infof("libcontainerd: new containerd process, pid: %d", cmd.Process.Pid)
if err := setOOMScore(cmd.Process.Pid, r.oomScore); err != nil {
system.KillProcess(cmd.Process.Pid)
@ -424,11 +449,6 @@ func (r *remote) runContainerdDaemon() error {
return err
}
r.daemonWaitCh = make(chan struct{})
go func() {
cmd.Wait()
close(r.daemonWaitCh)
}() // Reap our child when needed
r.daemonPid = cmd.Process.Pid
return nil
}

View File

@ -39,10 +39,9 @@ type FlushOption struct {
}
// HyperVIsolationOption is a CreateOption that indicates whether the runtime
// should start the container as a Hyper-V container, and if so, the sandbox path.
// should start the container as a Hyper-V container.
type HyperVIsolationOption struct {
IsHyperV bool
SandboxPath string `json:",omitempty"`
IsHyperV bool
}
// LayerOption is a CreateOption that indicates to the runtime the layer folder

View File

@ -1,4 +1,4 @@
FROM golang:1.7.5-alpine
FROM golang:1.8.3-alpine
RUN apk add -U git bash curl gcc musl-dev make

View File

@ -2,7 +2,7 @@ FROM aarch64/ubuntu:xenial
RUN apt-get update && apt-get install -y git golang-go curl
ENV GO_VERSION 1.7.5
ENV GO_VERSION 1.8.3
ENV GOARCH arm64
ENV PATH /go/bin:/usr/src/go/bin:$PATH

View File

@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y \
gcc \
make
ENV GO_VERSION 1.7.5
ENV GO_VERSION 1.8.3
RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" \
| tar -xzC /usr/local
ENV PATH /go/bin:/usr/local/go/bin:$PATH

Some files were not shown because too many files have changed in this diff Show More