1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #19490 from cyphar/remove-dockerinit

Remove dockerinit once and for all
This commit is contained in:
Arnaud Porterie 2016-01-26 08:27:35 -08:00
commit 7a97e938e2
47 changed files with 79 additions and 348 deletions

View file

@ -96,8 +96,7 @@ RUN set -x \
ENV PATH /osxcross/target/bin:$PATH
# install seccomp
# this can be changed to the ubuntu package libseccomp-dev if dockerinit is removed,
# we need libseccomp.a (which the package does not provide) for dockerinit
# TODO: switch to libseccomp-dev since dockerinit is gone
ENV SECCOMP_VERSION 2.2.3
RUN set -x \
&& export SECCOMP_PATH="$(mktemp -d)" \
@ -114,7 +113,7 @@ RUN set -x \
# Install Go
# 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
# will need updating, to avoid errors. Ping #docker-maintainers on IRC
# with a heads-up.
ENV GO_VERSION 1.5.3
RUN curl -fsSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" \

View file

@ -111,8 +111,7 @@ RUN git clone https://github.com/golang/lint.git /go/src/github.com/golang/lint
&& go install -v github.com/golang/lint/golint
# install seccomp
# this can be changed to the ubuntu package libseccomp-dev if dockerinit is removed,
# we need libseccomp.a (which the package does not provide) for dockerinit
# TODO: switch to libseccomp-dev since dockerinit is gone
ENV SECCOMP_VERSION 2.2.3
RUN set -x \
&& export SECCOMP_PATH="$(mktemp -d)" \

View file

@ -42,8 +42,7 @@ RUN cd /usr/local/lvm2 \
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL
# install seccomp
# this can be changed to the ubuntu package libseccomp-dev if dockerinit is removed,
# we need libseccomp.a (which the package does not provide) for dockerinit
# TODO: switch to libseccomp-dev since dockerinit is gone
ENV SECCOMP_VERSION v2.2.3
RUN set -x \
&& export SECCOMP_PATH=$(mktemp -d) \

View file

@ -74,8 +74,6 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
fmt.Fprintf(cli.out, " Goroutines: %d\n", info.NGoroutines)
fmt.Fprintf(cli.out, " System Time: %s\n", info.SystemTime)
fmt.Fprintf(cli.out, " EventsListeners: %d\n", info.NEventsListener)
fmt.Fprintf(cli.out, " Init SHA1: %s\n", info.InitSha1)
fmt.Fprintf(cli.out, " Init Path: %s\n", info.InitPath)
fmt.Fprintf(cli.out, " Docker Root Dir: %s\n", info.DockerRootDir)
}

View file

@ -63,10 +63,6 @@ func (container *Container) CreateDaemonEnvironment(linkedEnv []string) []string
env := []string{
"PATH=" + system.DefaultPathEnv,
"HOSTNAME=" + fullHostname,
// Note: we don't set HOME here because it'll get autoset intelligently
// based on the value of USER inside dockerinit, but only if it isn't
// set already (ie, that can be overridden by setting HOME via -e or ENV
// in a Dockerfile).
}
if container.Config.Tty {
env = append(env, "TERM=xterm")

View file

@ -118,9 +118,7 @@ for version in "${versions[@]}"; do
echo >> "$version/Dockerfile"
# fedora does not have a libseccomp.a for compiling static dockerinit
# ONLY install libseccomp.a from source, this can be removed once dockerinit is removed
# TODO remove this manual seccomp compilation once dockerinit is gone or no longer needs to be statically compiled
# TODO remove this since dockerinit is finally gone
case "$from" in
fedora:*)
awk '$1 == "ENV" && $2 == "SECCOMP_VERSION" { print; exit }' ../../../Dockerfile >> "$version/Dockerfile"

View file

@ -254,7 +254,6 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
c.Command = &execdriver.Command{
CommonCommand: execdriver.CommonCommand{
ID: c.ID,
InitPath: "/.dockerinit",
MountLabel: c.GetMountLabel(),
Network: en,
ProcessConfig: processConfig,

View file

@ -124,7 +124,6 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
CommonCommand: execdriver.CommonCommand{
ID: c.ID,
Rootfs: c.BaseFS,
InitPath: "/.dockerinit",
WorkingDir: c.Config.WorkingDir,
Network: en,
MountLabel: c.GetMountLabel(),

View file

@ -688,8 +688,7 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e
}
// setupInitLayer populates a directory with mountpoints suitable
// for bind-mounting dockerinit into the container. The mountpoint is simply an
// empty file at /.dockerinit
// for bind-mounting things into the container.
//
// This extra layer is used by all containers as the top-most ro layer. It protects
// the container from unwanted side-effects on the rw layer.
@ -699,7 +698,6 @@ func setupInitLayer(initLayer string, rootUID, rootGID int) error {
"/dev/shm": "dir",
"/proc": "dir",
"/sys": "dir",
"/.dockerinit": "file",
"/.dockerenv": "file",
"/etc/resolv.conf": "file",
"/etc/hosts": "file",

View file

@ -131,7 +131,6 @@ type CommonProcessConfig struct {
type CommonCommand struct {
ContainerPid int `json:"container_pid"` // the pid for the process inside a container
ID string `json:"id"`
InitPath string `json:"initpath"` // dockerinit
MountLabel string `json:"mount_label"` // TODO Windows. More involved, but can be factored out
Mounts []Mount `json:"mounts"`
Network *Network `json:"network"`

View file

@ -49,11 +49,6 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
logrus.Errorf("Could not read system memory info: %v", err)
}
// if we still have the original dockerinit binary from before
// we copied it locally, let's return the path to that, since
// that's more intuitive (the copied path is trivial to derive
// by hand given VERSION)
initPath := utils.DockerInitPath("")
sysInfo := sysinfo.New(true)
var cRunning, cPaused, cStopped int32
@ -94,8 +89,6 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
OSType: platform.OSType,
Architecture: platform.Architecture,
RegistryConfig: daemon.RegistryService.Config,
InitSha1: dockerversion.InitSHA1,
InitPath: initPath,
NCPU: runtime.NumCPU(),
MemTotal: meminfo.MemTotal,
DockerRootDir: daemon.configStore.Root,

View file

@ -1,11 +0,0 @@
package main
import (
_ "github.com/docker/docker/daemon/execdriver/native"
"github.com/docker/docker/pkg/reexec"
)
func main() {
// Running in init mode
reexec.Init()
}

View file

@ -9,8 +9,5 @@ const (
GitCommit string = "library-import"
Version string = "library-import"
BuildTime string = "library-import"
IAmStatic string = "library-import"
InitSHA1 string = "library-import"
InitPath string = "library-import"
)

View file

@ -76,7 +76,6 @@ _dockerfile_env() {
clean() {
local packages=(
"${PROJECT}/docker" # package main
"${PROJECT}/dockerinit" # package main
"${PROJECT}/integration-cli" # external tests
)
local dockerPlatforms=( ${DOCKER_ENGINE_OSARCH:="linux/amd64"} $(_dockerfile_env DOCKER_CROSSPLATFORMS) )

View file

@ -237,7 +237,6 @@ test_env() {
HOME="$ABS_DEST/fake-HOME" \
PATH="$PATH" \
TEMP="$TEMP" \
TEST_DOCKERINIT_PATH="$TEST_DOCKERINIT_PATH" \
"$@"
}

View file

@ -17,14 +17,12 @@ override_dh_auto_test:
./bundles/$(VERSION)/dynbinary/docker -v
override_dh_strip:
# the SHA1 of dockerinit is important: don't strip it
# also, Go has lots of problems with stripping, so just don't
# Go has lots of problems with stripping, so just don't
override_dh_auto_install:
mkdir -p debian/docker-engine/usr/bin
cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary/docker)" debian/docker-engine/usr/bin/docker
mkdir -p debian/docker-engine/usr/lib/docker
cp -aT "$$(readlink -f bundles/$(VERSION)/dynbinary/dockerinit)" debian/docker-engine/usr/lib/docker/dockerinit
override_dh_installinit:
# use "docker" as our service name, not "docker-engine"

View file

@ -11,11 +11,6 @@ URL: https://dockerproject.org
Vendor: Docker
Packager: Docker <support@docker.com>
# docker builds in a checksum of dockerinit into docker,
# # so stripping the binaries breaks docker
%global __os_install_post %{_rpmconfigdir}/brp-compress
%global debug_package %{nil}
# is_systemd conditional
%if 0%{?fedora} >= 21 || 0%{?centos} >= 7 || 0%{?rhel} >= 7 || 0%{?suse_version} >= 1300
%global is_systemd 1
@ -124,10 +119,6 @@ export DOCKER_GITCOMMIT=%{_gitcommit}
install -d $RPM_BUILD_ROOT/%{_bindir}
install -p -m 755 bundles/%{_origversion}/dynbinary/docker-%{_origversion} $RPM_BUILD_ROOT/%{_bindir}/docker
# install dockerinit
install -d $RPM_BUILD_ROOT/%{_libexecdir}/docker
install -p -m 755 bundles/%{_origversion}/dynbinary/dockerinit-%{_origversion} $RPM_BUILD_ROOT/%{_libexecdir}/docker/dockerinit
# install udev rules
install -d $RPM_BUILD_ROOT/%{_sysconfdir}/udev/rules.d
install -p -m 644 contrib/udev/80-docker.rules $RPM_BUILD_ROOT/%{_sysconfdir}/udev/rules.d/80-docker.rules
@ -175,7 +166,6 @@ install -p -m 644 contrib/syntax/nano/Dockerfile.nanorc $RPM_BUILD_ROOT/usr/shar
%files
%doc AUTHORS CHANGELOG.md CONTRIBUTING.md LICENSE MAINTAINERS NOTICE README.md
/%{_bindir}/docker
/%{_libexecdir}/docker/dockerinit
/%{_sysconfdir}/udev/rules.d/80-docker.rules
%if 0%{?is_systemd}
/%{_unitdir}/docker.service

View file

@ -1,33 +0,0 @@
#!/bin/bash
set -e
IAMSTATIC="true"
source "${MAKEDIR}/.go-autogen"
# dockerinit still needs to be a static binary, even if docker is dynamic
go build \
-o "$DEST/dockerinit-$VERSION" \
"${BUILDFLAGS[@]}" \
-ldflags "
$LDFLAGS
$LDFLAGS_STATIC
-extldflags \"$EXTLDFLAGS_STATIC\"
" \
./dockerinit
echo "Created binary: $DEST/dockerinit-$VERSION"
ln -sf "dockerinit-$VERSION" "$DEST/dockerinit"
sha1sum=
if command -v sha1sum &> /dev/null; then
sha1sum=sha1sum
elif command -v shasum &> /dev/null; then
# Mac OS X - why couldn't they just use the same command name and be happy?
sha1sum=shasum
else
echo >&2 'error: cannot find sha1sum command or equivalent'
exit 1
fi
# sha1 our new dockerinit to ensure separate docker and dockerinit always run in a perfect pair compiled for one another
export DOCKER_INITSHA1=$($sha1sum "$DEST/dockerinit-$VERSION" | cut -d' ' -f1)

View file

@ -1,31 +0,0 @@
#!/bin/bash
set -e
IAMSTATIC="true"
source "${MAKEDIR}/.go-autogen"
# dockerinit still needs to be a static binary, even if docker is dynamic
go build --compiler=gccgo \
-o "$DEST/dockerinit-$VERSION" \
"${BUILDFLAGS[@]}" \
--gccgoflags "
-g
-Wl,--no-export-dynamic
$EXTLDFLAGS_STATIC
-lnetgo
" \
./dockerinit
echo "Created binary: $DEST/dockerinit-$VERSION"
ln -sf "dockerinit-$VERSION" "$DEST/dockerinit"
sha1sum=
if command -v sha1sum &> /dev/null; then
sha1sum=sha1sum
else
echo >&2 'error: cannot find sha1sum command or equivalent'
exit 1
fi
# sha1 our new dockerinit to ensure separate docker and dockerinit always run in a perfect pair compiled for one another
export DOCKER_INITSHA1=$($sha1sum "$DEST/dockerinit-$VERSION" | cut -d' ' -f1)

View file

@ -14,10 +14,7 @@ const (
GitCommit string = "$GITCOMMIT"
Version string = "$VERSION"
BuildTime string = "$BUILDTIME"
IAmStatic string = "${IAMSTATIC:-true}"
InitSHA1 string = "$DOCKER_INITSHA1"
InitPath string = "$DOCKER_INITPATH"
)
// AUTOGENERATED FILE; see $BASH_SOURCE
DVEOF
@ -44,9 +41,9 @@ When make binary is run, the Dockerfile prepares the build environment by:
make.sh invokes hack/make/.go-autogen to:
- Run rsrc to create a binary file (autogen/winresources/rsrc.syso) that
contains the manifest and icon. This file is automatically picked up by
'go build', so no post-processing steps are required. The sources for
- Run rsrc to create a binary file (autogen/winresources/rsrc.syso) that
contains the manifest and icon. This file is automatically picked up by
'go build', so no post-processing steps are required. The sources for
rsrc.syso are under hack/make/.resources-windows.
*/

View file

@ -1,16 +1,6 @@
#!/bin/bash
set -e
if [ -z "$DOCKER_CLIENTONLY" ]; then
source "${MAKEDIR}/.dockerinit"
hash_files "$DEST/dockerinit-$VERSION"
else
# DOCKER_CLIENTONLY must be truthy, so we don't need to bother with dockerinit :)
export DOCKER_INITSHA1=""
fi
# DOCKER_INITSHA1 is exported so that other bundlescripts can easily access it later without recalculating it
(
export IAMSTATIC="false"
export LDFLAGS_STATIC_DOCKER=''

View file

@ -1,16 +1,6 @@
#!/bin/bash
set -e
if [ -z "$DOCKER_CLIENTONLY" ]; then
source "${MAKEDIR}/.dockerinit-gccgo"
hash_files "$DEST/dockerinit-$VERSION"
else
# DOCKER_CLIENTONLY must be truthy, so we don't need to bother with dockerinit :)
export DOCKER_INITSHA1=""
fi
# DOCKER_INITSHA1 is exported so that other bundlescripts can easily access it later without recalculating it
(
export IAMSTATIC="false"
export EXTLDFLAGS_STATIC=''

View file

@ -22,7 +22,7 @@ clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b
clone git golang.org/x/net 47990a1ba55743e6ef1affd3a14e5bac8553615d https://github.com/golang/net.git
clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3
clone git github.com/docker/go-connections v0.1.2
clone git github.com/docker/engine-api v0.2.2
clone git github.com/docker/engine-api bdbab71ec21209ef56dffdbe42c9d21843c30862
clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
clone git github.com/imdario/mergo 0.2.1

View file

@ -27,10 +27,10 @@ func (s *DockerSuite) TestDiffFilenameShownInOutput(c *check.C) {
}
// test to ensure GH #3840 doesn't occur any more
func (s *DockerSuite) TestDiffEnsureDockerinitFilesAreIgnored(c *check.C) {
func (s *DockerSuite) TestDiffEnsureInitLayerFilesAreIgnored(c *check.C) {
testRequires(c, DaemonIsLinux)
// this is a list of files which shouldn't show up in `docker diff`
dockerinitFiles := []string{"/etc/resolv.conf", "/etc/hostname", "/etc/hosts", "/.dockerinit", "/.dockerenv"}
initLayerFiles := []string{"/etc/resolv.conf", "/etc/hostname", "/etc/hosts", "/.dockerenv"}
containerCount := 5
// we might not run into this problem from the first run, so start a few containers
@ -41,7 +41,7 @@ func (s *DockerSuite) TestDiffEnsureDockerinitFilesAreIgnored(c *check.C) {
cleanCID := strings.TrimSpace(out)
out, _ = dockerCmd(c, "diff", cleanCID)
for _, filename := range dockerinitFiles {
for _, filename := range initLayerFiles {
c.Assert(out, checker.Not(checker.Contains), filename)
}
}

View file

@ -224,7 +224,6 @@ const (
43 16 0:34 / /proc/fs/nfsd rw,nosuid,nodev,noexec,relatime - nfsd nfsd rw
44 15 0:35 / /home/tianon/.gvfs rw,nosuid,nodev,relatime - fuse.gvfs-fuse-daemon gvfs-fuse-daemon rw,user_id=1000,group_id=1000
68 15 0:3336 / /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd rw,relatime - aufs none rw,si=9b4a7640128db39c
85 68 8:6 /var/lib/docker/init/dockerinit-0.7.2-dev//deleted /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/.dockerinit rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered
86 68 8:6 /var/lib/docker/containers/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/config.env /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/.dockerenv rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered
87 68 8:6 /etc/resolv.conf /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/etc/resolv.conf rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered
88 68 8:6 /var/lib/docker/containers/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/hostname /var/lib/docker/aufs/mnt/3597a1a6d6298c1decc339ebb90aad6f7d6ba2e15af3131b1f85e7ee4787a0cd/etc/hostname rw,noatime,nodiratime - ext4 /dev/sda6 rw,data=ordered

View file

@ -210,7 +210,7 @@ the file "./VERSION". This binary is usually installed somewhere like
### Dynamic Daemon / Client-only Binary
If you are only interested in a Docker client binary, set `DOCKER_CLIENTONLY` to a non-empty value using something similar to the following: (which will prevent the extra step of compiling dockerinit)
If you are only interested in a Docker client binary, set `DOCKER_CLIENTONLY` to a non-empty value using something similar to the following:
```bash
export DOCKER_CLIENTONLY=1
@ -228,37 +228,6 @@ following:
This will create "./bundles/$VERSION/dynbinary/docker-$VERSION", which for
client-only builds is the important file to grab and install as appropriate.
For daemon builds, you will also need to grab and install
"./bundles/$VERSION/dynbinary/dockerinit-$VERSION", which is created from the
minimal set of Docker's codebase that _must_ be compiled statically (and is thus
a pure static binary). The acceptable locations Docker will search for this file
are as follows (in order):
* as "dockerinit" in the same directory as the daemon binary (ie, if docker is
installed at "/usr/bin/docker", then "/usr/bin/dockerinit" will be the first
place this file is searched for)
* "/usr/libexec/docker/dockerinit" or "/usr/local/libexec/docker/dockerinit"
([FHS 3.0 Draft](https://www.linuxbase.org/betaspecs/fhs/fhs.html#usrlibexec))
* "/usr/lib/docker/dockerinit" or "/usr/local/lib/docker/dockerinit" ([FHS
2.3](https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA))
If (and please, only if) one of the paths above is insufficient due to distro
policy or similar issues, you may use the `DOCKER_INITPATH` environment variable
at compile-time as follows to set a different path for Docker to search:
```bash
export DOCKER_INITPATH=/usr/lib/docker.io/dockerinit
```
If you find yourself needing this, please don't hesitate to reach out to Tianon
to see if it would be reasonable or helpful to add more paths to Docker's list,
especially if there's a relevant standard worth referencing (such as the FHS).
Also, it goes without saying, but for the purposes of the daemon please consider
these two binaries ("docker" and "dockerinit") as if they were a single unit.
Mixing and matching can cause undesired consequences, and will fail to run
properly.
## System Dependencies
### Runtime Dependencies

View file

@ -1,124 +1,17 @@
package utils
import (
"crypto/sha1"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/docker/distribution/registry/api/errcode"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/stringid"
)
// SelfPath figures out the absolute path of our own binary (if it's still around).
func SelfPath() string {
path, err := exec.LookPath(os.Args[0])
if err != nil {
if os.IsNotExist(err) {
return ""
}
if execErr, ok := err.(*exec.Error); ok && os.IsNotExist(execErr.Err) {
return ""
}
panic(err)
}
path, err = filepath.Abs(path)
if err != nil {
if os.IsNotExist(err) {
return ""
}
panic(err)
}
return path
}
func dockerInitSha1(target string) string {
f, err := os.Open(target)
if err != nil {
return ""
}
defer f.Close()
h := sha1.New()
_, err = io.Copy(h, f)
if err != nil {
return ""
}
return hex.EncodeToString(h.Sum(nil))
}
func isValidDockerInitPath(target string, selfPath string) bool { // target and selfPath should be absolute (InitPath and SelfPath already do this)
if target == "" {
return false
}
if dockerversion.IAmStatic == "true" {
if selfPath == "" {
return false
}
if target == selfPath {
return true
}
targetFileInfo, err := os.Lstat(target)
if err != nil {
return false
}
selfPathFileInfo, err := os.Lstat(selfPath)
if err != nil {
return false
}
return os.SameFile(targetFileInfo, selfPathFileInfo)
}
return dockerversion.InitSHA1 != "" && dockerInitSha1(target) == dockerversion.InitSHA1
}
// DockerInitPath figures out the path of our dockerinit (which may be SelfPath())
func DockerInitPath(localCopy string) string {
selfPath := SelfPath()
if isValidDockerInitPath(selfPath, selfPath) {
// if we're valid, don't bother checking anything else
return selfPath
}
var possibleInits = []string{
localCopy,
dockerversion.InitPath,
filepath.Join(filepath.Dir(selfPath), "dockerinit"),
// FHS 3.0 Draft: "/usr/libexec includes internal binaries that are not intended to be executed directly by users or shell scripts. Applications may use a single subdirectory under /usr/libexec."
// https://www.linuxbase.org/betaspecs/fhs/fhs.html#usrlibexec
"/usr/libexec/docker/dockerinit",
"/usr/local/libexec/docker/dockerinit",
// FHS 2.3: "/usr/lib includes object files, libraries, and internal binaries that are not intended to be executed directly by users or shell scripts."
// https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA
"/usr/lib/docker/dockerinit",
"/usr/local/lib/docker/dockerinit",
}
for _, dockerInit := range possibleInits {
if dockerInit == "" {
continue
}
path, err := exec.LookPath(dockerInit)
if err == nil {
path, err = filepath.Abs(path)
if err != nil {
// LookPath already validated that this file exists and is executable (following symlinks), so how could Abs fail?
panic(err)
}
if isValidDockerInitPath(path, selfPath) {
return path
}
}
}
return ""
}
var globalTestID string
// TestDirectory creates a new temporary directory and returns its path.

View file

@ -10,6 +10,8 @@ import (
"path/filepath"
"strings"
"time"
"github.com/docker/go-connections/tlsconfig"
)
// Client is the API client that performs all operations
@ -41,21 +43,27 @@ type Client struct {
func NewEnvClient() (*Client, error) {
var transport *http.Transport
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
tlsc := &tls.Config{}
cert, err := tls.LoadX509KeyPair(filepath.Join(dockerCertPath, "cert.pem"), filepath.Join(dockerCertPath, "key.pem"))
options := tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
}
tlsc, err := tlsconfig.Client(options)
if err != nil {
return nil, fmt.Errorf("Error loading x509 key pair: %s", err)
return nil, err
}
tlsc.Certificates = append(tlsc.Certificates, cert)
tlsc.InsecureSkipVerify = os.Getenv("DOCKER_TLS_VERIFY") == ""
transport = &http.Transport{
TLSClientConfig: tlsc,
}
}
return NewClient(os.Getenv("DOCKER_HOST"), os.Getenv("DOCKER_API_VERSION"), transport, nil)
host := os.Getenv("DOCKER_HOST")
if host == "" {
host = DefaultDockerHost
}
return NewClient(host, os.Getenv("DOCKER_API_VERSION"), transport, nil)
}
// NewClient initializes a new API client for the given host and API version.

View file

@ -0,0 +1,6 @@
// +build windows darwin
package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "tcp://127.0.0.1:2375"

View file

@ -0,0 +1,6 @@
// +build linux freebsd
package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "unix:///var/run/docker.sock"

View file

@ -27,11 +27,8 @@ func (cli *Client) ContainerCommit(options types.ContainerCommitOptions) (types.
if err != nil {
return response, err
}
defer ensureReaderClosed(resp)
if err := json.NewDecoder(resp.body).Decode(&response); err != nil {
return response, err
}
return response, nil
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View file

@ -39,18 +39,7 @@ func (cli *Client) ContainerCreate(config *container.Config, hostConfig *contain
return response, err
}
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
return response, imageNotFoundError{config.Image}
}
if err != nil {
return response, err
}
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&response); err != nil {
return response, err
}
return response, nil
err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err
}

View file

@ -19,10 +19,10 @@ func (cli *Client) ContainerInspect(containerID string) (types.ContainerJSON, er
}
return types.ContainerJSON{}, err
}
defer ensureReaderClosed(serverResp)
var response types.ContainerJSON
err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err
}

View file

@ -46,9 +46,9 @@ func (cli *Client) ContainerList(options types.ContainerListOptions) ([]types.Co
if err != nil {
return nil, err
}
defer ensureReaderClosed(resp)
var containers []types.Container
err = json.NewDecoder(resp.body).Decode(&containers)
ensureReaderClosed(resp)
return containers, err
}

View file

@ -20,8 +20,8 @@ func (cli *Client) ContainerTop(containerID string, arguments []string) (types.C
if err != nil {
return response, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View file

@ -15,11 +15,8 @@ func (cli *Client) ContainerDiff(containerID string) ([]types.ContainerChange, e
if err != nil {
return changes, err
}
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&changes); err != nil {
return changes, err
}
return changes, nil
err = json.NewDecoder(serverResp.body).Decode(&changes)
ensureReaderClosed(serverResp)
return changes, err
}

View file

@ -13,8 +13,8 @@ func (cli *Client) ContainerExecCreate(config types.ExecConfig) (types.Container
if err != nil {
return response, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}
@ -41,8 +41,8 @@ func (cli *Client) ContainerExecInspect(execID string) (types.ContainerExecInspe
if err != nil {
return response, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View file

@ -14,10 +14,8 @@ func (cli *Client) ImageHistory(imageID string) ([]types.ImageHistory, error) {
if err != nil {
return history, err
}
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&history); err != nil {
return history, err
}
return history, nil
err = json.NewDecoder(serverResp.body).Decode(&history)
ensureReaderClosed(serverResp)
return history, err
}

View file

@ -32,8 +32,8 @@ func (cli *Client) ImageList(options types.ImageListOptions) ([]types.Image, err
if err != nil {
return images, err
}
defer ensureReaderClosed(serverResp)
err = json.NewDecoder(serverResp.body).Decode(&images)
ensureReaderClosed(serverResp)
return images, err
}

View file

@ -22,9 +22,9 @@ func (cli *Client) ImageRemove(options types.ImageRemoveOptions) ([]types.ImageD
if err != nil {
return nil, err
}
defer ensureReaderClosed(resp)
var dels []types.ImageDelete
err = json.NewDecoder(resp.body).Decode(&dels)
ensureReaderClosed(resp)
return dels, err
}

View file

@ -27,9 +27,9 @@ func (cli *Client) ImageSearch(options types.ImageSearchOptions, privilegeFunc R
if err != nil {
return results, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&results)
ensureReaderClosed(resp)
return results, err
}

View file

@ -19,9 +19,9 @@ func (cli *Client) RegistryLogin(auth types.AuthConfig) (types.AuthResponse, err
if err != nil {
return types.AuthResponse{}, err
}
defer ensureReaderClosed(resp)
var response types.AuthResponse
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View file

@ -65,8 +65,8 @@ func (cli *Client) NetworkList(options types.NetworkListOptions) ([]types.Networ
if err != nil {
return networkResources, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&networkResources)
ensureReaderClosed(resp)
return networkResources, err
}
@ -80,7 +80,7 @@ func (cli *Client) NetworkInspect(networkID string) (types.NetworkResource, erro
}
return networkResource, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&networkResource)
ensureReaderClosed(resp)
return networkResource, err
}

View file

@ -12,9 +12,9 @@ func (cli *Client) ServerVersion() (types.Version, error) {
if err != nil {
return types.Version{}, err
}
defer ensureReaderClosed(resp)
var server types.Version
err = json.NewDecoder(resp.body).Decode(&server)
ensureReaderClosed(resp)
return server, err
}

View file

@ -25,9 +25,9 @@ func (cli *Client) VolumeList(filter filters.Args) (types.VolumesListResponse, e
if err != nil {
return volumes, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&volumes)
ensureReaderClosed(resp)
return volumes, err
}
@ -41,8 +41,8 @@ func (cli *Client) VolumeInspect(volumeID string) (types.Volume, error) {
}
return volume, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&volume)
ensureReaderClosed(resp)
return volume, err
}
@ -53,8 +53,8 @@ func (cli *Client) VolumeCreate(options types.VolumeCreateRequest) (types.Volume
if err != nil {
return volume, err
}
defer ensureReaderClosed(resp)
err = json.NewDecoder(resp.body).Decode(&volume)
ensureReaderClosed(resp)
return volume, err
}

View file

@ -151,6 +151,11 @@ func (rp *RestartPolicy) IsUnlessStopped() bool {
return rp.Name == "unless-stopped"
}
// IsSame compares two RestartPolicy to see if they are the same
func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
}
// LogConfig represents the logging configuration of the container.
type LogConfig struct {
Type string
@ -178,7 +183,7 @@ type Resources struct {
KernelMemory int64 // Kernel memory limit (in bytes)
Memory int64 // Memory limit (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
OomKillDisable *bool // Whether to disable OOM Killer or not
PidsLimit int64 // Setting pids limit for a container
@ -190,6 +195,7 @@ type Resources struct {
type UpdateConfig struct {
// Contains container's resources (cgroups, ulimits)
Resources
RestartPolicy RestartPolicy
}
// HostConfig the non-portable Config structure of a container.

View file

@ -142,6 +142,7 @@ type Container struct {
SizeRw int64 `json:",omitempty"`
SizeRootFs int64 `json:",omitempty"`
Labels map[string]string
State string
Status string
HostConfig struct {
NetworkMode string `json:",omitempty"`
@ -198,6 +199,7 @@ type Info struct {
Images int
Driver string
DriverStatus [][2]string
SystemStatus [][2]string
Plugins PluginsInfo
MemoryLimit bool
SwapLimit bool
@ -222,8 +224,6 @@ type Info struct {
Architecture string
IndexServerAddress string
RegistryConfig *registry.ServiceConfig
InitSha1 string
InitPath string
NCPU int
MemTotal int64
DockerRootDir string
@ -388,6 +388,7 @@ type NetworkResource struct {
Scope string
Driver string
IPAM network.IPAM
Internal bool
Containers map[string]EndpointResource
Options map[string]string
}