2014-02-25 16:17:48 +00:00
package main
import (
2014-07-21 19:10:47 +00:00
"archive/tar"
2014-11-13 03:14:15 +00:00
"bytes"
2014-10-25 18:29:18 +00:00
"encoding/json"
2014-02-25 16:17:48 +00:00
"fmt"
2014-07-21 19:10:47 +00:00
"io/ioutil"
2014-05-13 18:49:12 +00:00
"os"
2014-02-25 16:17:48 +00:00
"path/filepath"
2014-12-04 01:52:06 +00:00
"reflect"
2014-10-13 20:14:35 +00:00
"regexp"
2015-02-18 07:20:20 +00:00
"runtime"
2014-11-13 03:14:15 +00:00
"strconv"
2014-05-13 18:49:12 +00:00
"strings"
2014-11-13 03:14:15 +00:00
"text/template"
2014-05-22 22:12:41 +00:00
"time"
2014-05-09 22:26:41 +00:00
2015-09-05 19:49:06 +00:00
"github.com/docker/docker/builder/dockerfile/command"
2016-12-30 17:23:00 +00:00
"github.com/docker/docker/integration-cli/checker"
2017-03-23 17:35:22 +00:00
"github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/integration-cli/cli/build"
2014-09-30 06:23:36 +00:00
"github.com/docker/docker/pkg/archive"
2015-03-24 11:25:26 +00:00
"github.com/docker/docker/pkg/stringutils"
2016-12-30 17:23:00 +00:00
"github.com/docker/docker/pkg/testutil"
icmd "github.com/docker/docker/pkg/testutil/cmd"
2015-04-18 16:46:47 +00:00
"github.com/go-check/check"
2014-02-25 16:17:48 +00:00
)
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildJSONEmptyRun ( c * check . C ) {
2017-03-23 17:35:22 +00:00
cli . BuildCmd ( c , "testbuildjsonemptyrun" , build . WithDockerfile ( `
2015-01-09 01:00:00 +00:00
FROM busybox
RUN [ ]
2017-01-10 18:16:25 +00:00
` ) )
2015-01-09 01:00:00 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildShCmdJSONEntrypoint ( c * check . C ) {
2014-10-27 21:15:28 +00:00
name := "testbuildshcmdjsonentrypoint"
2017-01-10 18:16:25 +00:00
expected := "/bin/sh -c echo test"
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2017-01-10 18:16:25 +00:00
expected = "cmd /S /C echo test"
}
2014-10-27 21:15:28 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-27 21:15:28 +00:00
FROM busybox
2016-01-21 21:13:37 +00:00
ENTRYPOINT [ "echo" ]
2014-10-27 21:15:28 +00:00
CMD echo test
2017-01-10 18:16:25 +00:00
` ) )
2015-07-14 06:35:36 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , name )
2014-10-27 21:15:28 +00:00
2017-01-10 18:16:25 +00:00
if strings . TrimSpace ( out ) != expected {
c . Fatalf ( "CMD did not contain %q : %q" , expected , out )
2014-10-27 21:15:28 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementUser ( c * check . C ) {
2016-01-21 21:13:37 +00:00
// Windows does not support FROM scratch or the USER command
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-25 18:29:18 +00:00
name := "testbuildenvironmentreplacement"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-25 18:29:18 +00:00
FROM scratch
ENV user foo
USER $ { user }
2017-01-10 18:16:25 +00:00
` ) )
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "Config.User" )
2014-10-25 18:29:18 +00:00
if res != ` "foo" ` {
2015-04-18 16:46:47 +00:00
c . Fatal ( "User foo from environment not in Config.User on image" )
2014-10-25 18:29:18 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementVolume ( c * check . C ) {
2014-10-25 18:29:18 +00:00
name := "testbuildenvironmentreplacement"
2016-02-04 21:06:12 +00:00
var volumePath string
2016-01-21 21:13:37 +00:00
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-01-21 21:13:37 +00:00
volumePath = "c:/quux"
} else {
volumePath = "/quux"
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2016-02-04 21:06:12 +00:00
FROM ` +minimalBaseImage()+ `
2016-01-21 21:13:37 +00:00
ENV volume ` +volumePath+ `
2014-10-25 18:29:18 +00:00
VOLUME $ { volume }
2017-01-10 18:16:25 +00:00
` ) )
2014-10-25 18:29:18 +00:00
var volumes map [ string ] interface { }
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.Volumes" , & volumes )
2016-01-21 21:13:37 +00:00
if _ , ok := volumes [ volumePath ] ; ! ok {
c . Fatal ( "Volume " + volumePath + " from environment not in Config.Volumes on image" )
2014-10-25 18:29:18 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementExpose ( c * check . C ) {
2016-01-21 21:13:37 +00:00
// Windows does not support FROM scratch or the EXPOSE command
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-25 18:29:18 +00:00
name := "testbuildenvironmentreplacement"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-25 18:29:18 +00:00
FROM scratch
ENV port 80
EXPOSE $ { port }
2015-11-07 20:05:55 +00:00
ENV ports " 99 100 "
EXPOSE $ { ports }
2017-01-10 18:16:25 +00:00
` ) )
2014-10-25 18:29:18 +00:00
var exposedPorts map [ string ] interface { }
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.ExposedPorts" , & exposedPorts )
2015-11-07 20:05:55 +00:00
exp := [ ] int { 80 , 99 , 100 }
for _ , p := range exp {
tmp := fmt . Sprintf ( "%d/tcp" , p )
if _ , ok := exposedPorts [ tmp ] ; ! ok {
c . Fatalf ( "Exposed port %d from environment not in Config.ExposedPorts on image" , p )
}
2014-10-25 18:29:18 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementWorkdir ( c * check . C ) {
2014-10-25 18:29:18 +00:00
name := "testbuildenvironmentreplacement"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-25 18:29:18 +00:00
FROM busybox
ENV MYWORKDIR / work
RUN mkdir $ { MYWORKDIR }
WORKDIR $ { MYWORKDIR }
2017-01-10 18:16:25 +00:00
` ) )
res := inspectFieldJSON ( c , name , "Config.WorkingDir" )
2014-10-25 18:29:18 +00:00
2017-01-10 18:16:25 +00:00
expected := ` "/work" `
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2017-01-10 18:16:25 +00:00
expected = ` "C:\\work" `
}
if res != expected {
c . Fatalf ( "Workdir /workdir from environment not in Config.WorkingDir on image: %s" , res )
2014-10-25 18:29:18 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementAddCopy ( c * check . C ) {
2014-10-25 18:29:18 +00:00
name := "testbuildenvironmentreplacement"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
2016-02-04 21:06:12 +00:00
FROM ` +minimalBaseImage()+ `
2014-10-25 18:29:18 +00:00
ENV baz foo
ENV quux bar
ENV dot .
2015-01-29 02:28:48 +00:00
ENV fee fff
ENV gee ggg
2014-10-25 18:29:18 +00:00
ADD $ { baz } $ { dot }
COPY $ { quux } $ { dot }
2015-01-29 02:28:48 +00:00
ADD $ { zzz : - $ { fee } } $ { dot }
COPY $ { zzz : - $ { gee } } $ { dot }
2017-01-10 18:16:25 +00:00
` ) ,
withFile ( "foo" , "test1" ) ,
withFile ( "bar" , "test2" ) ,
withFile ( "fff" , "test3" ) ,
withFile ( "ggg" , "test4" ) ,
) )
2014-10-25 18:29:18 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementEnv ( c * check . C ) {
2016-01-21 21:13:37 +00:00
// ENV expansions work differently in Windows
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-25 18:29:18 +00:00
name := "testbuildenvironmentreplacement"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2015-01-29 02:28:48 +00:00
FROM busybox
ENV foo zzz
2014-10-25 18:29:18 +00:00
ENV bar $ { foo }
2015-01-29 02:28:48 +00:00
ENV abc1 = ' $ foo '
ENV env1 = $ foo env2 = $ { foo } env3 = "$foo" env4 = "${foo}"
RUN [ "$abc1" = ' $ foo ' ] && ( echo "$abc1" | grep - q foo )
ENV abc2 = "\$foo"
RUN [ "$abc2" = ' $ foo ' ] && ( echo "$abc2" | grep - q foo )
ENV abc3 ' $ foo '
RUN [ "$abc3" = ' $ foo ' ] && ( echo "$abc3" | grep - q foo )
ENV abc4 "\$foo"
RUN [ "$abc4" = ' $ foo ' ] && ( echo "$abc4" | grep - q foo )
2017-01-10 18:16:25 +00:00
` ) )
2014-10-25 18:29:18 +00:00
envResult := [ ] string { }
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.Env" , & envResult )
2014-10-25 18:29:18 +00:00
found := false
2015-01-29 02:28:48 +00:00
envCount := 0
2014-10-25 18:29:18 +00:00
for _ , env := range envResult {
parts := strings . SplitN ( env , "=" , 2 )
if parts [ 0 ] == "bar" {
found = true
2015-01-29 02:28:48 +00:00
if parts [ 1 ] != "zzz" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Could not find replaced var for env `bar`: got %q instead of `zzz`" , parts [ 1 ] )
2015-01-29 02:28:48 +00:00
}
} else if strings . HasPrefix ( parts [ 0 ] , "env" ) {
envCount ++
if parts [ 1 ] != "zzz" {
2017-03-01 09:49:54 +00:00
c . Fatalf ( "%s should be 'zzz' but instead its %q" , parts [ 0 ] , parts [ 1 ] )
2014-10-25 18:29:18 +00:00
}
2015-01-29 02:28:48 +00:00
} else if strings . HasPrefix ( parts [ 0 ] , "env" ) {
envCount ++
if parts [ 1 ] != "foo" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "%s should be 'foo' but instead its %q" , parts [ 0 ] , parts [ 1 ] )
2015-01-29 02:28:48 +00:00
}
2014-10-25 18:29:18 +00:00
}
}
if ! found {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Never found the `bar` env variable" )
2014-10-25 18:29:18 +00:00
}
2015-01-29 02:28:48 +00:00
if envCount != 4 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Didn't find all env vars - only saw %d\n%s" , envCount , envResult )
2015-01-29 02:28:48 +00:00
}
2014-10-25 18:29:18 +00:00
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildHandleEscapesInVolume ( c * check . C ) {
2016-01-21 21:13:37 +00:00
// The volume paths used in this test are invalid on Windows
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-25 17:58:57 +00:00
name := "testbuildhandleescapes"
2017-01-10 18:16:25 +00:00
testCases := [ ] struct {
volumeValue string
expected string
} {
{
volumeValue : "${FOO}" ,
expected : "bar" ,
} ,
{
volumeValue : ` \$ { FOO} ` ,
expected : "${FOO}" ,
} ,
// this test in particular provides *7* backslashes and expects 6 to come back.
// Like above, the first escape is swallowed and the rest are treated as
// literals, this one is just less obvious because of all the character noise.
{
volumeValue : ` \\\\\\\$ { FOO} ` ,
expected : ` \\\$ { FOO} ` ,
} ,
2014-10-25 17:58:57 +00:00
}
2017-01-10 18:16:25 +00:00
for _ , tc := range testCases {
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( fmt . Sprintf ( `
2014-10-25 17:58:57 +00:00
FROM scratch
ENV FOO bar
2017-01-10 18:16:25 +00:00
VOLUME % s
` , tc . volumeValue ) ) )
2014-10-25 17:58:57 +00:00
2017-01-10 18:16:25 +00:00
var result map [ string ] map [ string ] struct { }
inspectFieldAndUnmarshall ( c , name , "Config.Volumes" , & result )
if _ , ok := result [ tc . expected ] ; ! ok {
c . Fatalf ( "Could not find volume %s set from env foo in volumes table, got %q" , tc . expected , result )
}
2014-10-25 17:58:57 +00:00
2017-01-10 18:16:25 +00:00
// Remove the image for the next iteration
dockerCmd ( c , "rmi" , name )
2014-10-25 17:58:57 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildOnBuildLowercase ( c * check . C ) {
2014-10-21 19:26:20 +00:00
name := "testbuildonbuildlowercase"
name2 := "testbuildonbuildlowercase2"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-21 19:26:20 +00:00
FROM busybox
onbuild run echo quux
2017-01-10 18:16:25 +00:00
` ) )
2014-10-21 19:26:20 +00:00
2017-03-23 17:35:22 +00:00
result := buildImage ( name2 , build . WithDockerfile ( fmt . Sprintf ( `
2014-10-21 19:26:20 +00:00
FROM % s
2017-01-10 18:16:25 +00:00
` , name ) ) )
result . Assert ( c , icmd . Success )
2014-10-21 19:26:20 +00:00
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "quux" ) {
c . Fatalf ( "Did not receive the expected echo text, got %s" , result . Combined ( ) )
2014-10-21 19:26:20 +00:00
}
2017-01-10 18:16:25 +00:00
if strings . Contains ( result . Combined ( ) , "ONBUILD ONBUILD" ) {
c . Fatalf ( "Got an ONBUILD ONBUILD error with no error: got %s" , result . Combined ( ) )
2014-10-21 19:26:20 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvEscapes ( c * check . C ) {
2016-01-21 21:13:37 +00:00
// ENV expansions work differently in Windows
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-17 19:15:07 +00:00
name := "testbuildenvescapes"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-17 19:15:07 +00:00
FROM busybox
ENV TEST foo
CMD echo \ $
2017-01-10 18:16:25 +00:00
` ) )
2014-10-17 19:15:07 +00:00
2015-07-14 06:35:36 +00:00
out , _ := dockerCmd ( c , "run" , "-t" , name )
2014-10-17 19:15:07 +00:00
if strings . TrimSpace ( out ) != "$" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q" , strings . TrimSpace ( out ) )
2014-10-17 19:15:07 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvOverwrite ( c * check . C ) {
2016-01-21 21:13:37 +00:00
// ENV expansions work differently in Windows
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-17 19:15:07 +00:00
name := "testbuildenvoverwrite"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-17 19:15:07 +00:00
FROM busybox
ENV TEST foo
2014-10-25 18:29:18 +00:00
CMD echo $ { TEST }
2017-01-10 18:16:25 +00:00
` ) )
2014-10-17 19:15:07 +00:00
2015-07-14 06:35:36 +00:00
out , _ := dockerCmd ( c , "run" , "-e" , "TEST=bar" , "-t" , name )
2014-10-17 19:15:07 +00:00
if strings . TrimSpace ( out ) != "bar" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q" , strings . TrimSpace ( out ) )
2014-10-17 19:15:07 +00:00
}
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) why we disabled cache here ?
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildOnBuildCmdEntrypointJSON ( c * check . C ) {
2014-10-13 20:14:35 +00:00
name1 := "onbuildcmd"
name2 := "onbuildgenerated"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name1 , build . WithDockerfile ( `
2014-10-13 20:14:35 +00:00
FROM busybox
ONBUILD CMD [ "hello world" ]
ONBUILD ENTRYPOINT [ "echo" ]
2017-01-10 18:16:25 +00:00
ONBUILD RUN [ "true" ] ` ) )
2014-10-13 20:14:35 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name2 , build . WithDockerfile ( fmt . Sprintf ( ` FROM %s ` , name1 ) ) )
2014-10-13 20:14:35 +00:00
2016-01-25 23:58:03 +00:00
out , _ := dockerCmd ( c , "run" , name2 )
2014-10-13 20:14:35 +00:00
if ! regexp . MustCompile ( ` (?m)^hello world ` ) . MatchString ( out ) {
2016-01-25 23:58:03 +00:00
c . Fatalf ( "did not get echo output from onbuild. Got: %q" , out )
2014-10-13 20:14:35 +00:00
}
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) why we disabled cache here ?
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildOnBuildEntrypointJSON ( c * check . C ) {
2014-10-13 20:14:35 +00:00
name1 := "onbuildcmd"
name2 := "onbuildgenerated"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name1 , build . WithDockerfile ( `
2014-10-13 20:14:35 +00:00
FROM busybox
2017-01-10 18:16:25 +00:00
ONBUILD ENTRYPOINT [ "echo" ] ` ) )
2014-10-13 20:14:35 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name2 , build . WithDockerfile ( fmt . Sprintf ( "FROM %s\nCMD [\"hello world\"]\n" , name1 ) ) )
2014-10-13 20:14:35 +00:00
2016-01-25 23:58:03 +00:00
out , _ := dockerCmd ( c , "run" , name2 )
2014-10-13 20:14:35 +00:00
if ! regexp . MustCompile ( ` (?m)^hello world ` ) . MatchString ( out ) {
2015-04-18 16:46:47 +00:00
c . Fatal ( "got malformed output from onbuild" , out )
2014-10-13 20:14:35 +00:00
}
}
2015-05-25 06:51:10 +00:00
func ( s * DockerSuite ) TestBuildCacheAdd ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Windows doesn't have httpserver image yet
2014-08-18 10:13:43 +00:00
name := "testbuildtwoimageswithadd"
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , map [ string ] string {
2014-08-18 10:13:43 +00:00
"robots.txt" : "hello" ,
"index.html" : "world" ,
} )
defer server . Close ( )
2015-02-19 10:01:27 +00:00
2017-03-23 17:35:22 +00:00
cli . BuildCmd ( c , name , build . WithDockerfile ( fmt . Sprintf ( ` FROM scratch
2017-01-16 10:30:14 +00:00
ADD % s / robots . txt / ` , server . URL ( ) ) ) )
2017-03-23 17:35:22 +00:00
result := cli . Docker ( cli . Build ( name ) , build . WithDockerfile ( fmt . Sprintf ( ` FROM scratch
2017-01-16 10:30:14 +00:00
ADD % s / index . html / ` , server . URL ( ) ) ) )
result . Assert ( c , icmd . Success )
if strings . Contains ( result . Combined ( ) , "Using cache" ) {
2015-04-18 16:46:47 +00:00
c . Fatal ( "2nd build used cache on ADD, it shouldn't" )
2014-05-20 21:29:19 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildLastModified ( c * check . C ) {
2017-02-10 02:13:20 +00:00
// Temporary fix for #30890. TODO @jhowardmsft figure out what
// has changed in the master busybox image.
testRequires ( c , DaemonIsLinux )
2015-03-04 17:14:58 +00:00
name := "testbuildlastmodified"
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , map [ string ] string {
2015-03-04 17:14:58 +00:00
"file" : "hello" ,
} )
defer server . Close ( )
var out , out2 string
dFmt := ` FROM busybox
2016-10-06 07:53:30 +00:00
ADD % s / file / `
2015-03-09 23:56:51 +00:00
dockerfile := fmt . Sprintf ( dFmt , server . URL ( ) )
2015-03-04 17:14:58 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , build . WithDockerfile ( dockerfile ) )
2016-10-06 07:53:30 +00:00
out , _ = dockerCmd ( c , "run" , name , "ls" , "-le" , "/file" )
2015-03-04 17:14:58 +00:00
// Build it again and make sure the mtime of the file didn't change.
// Wait a few seconds to make sure the time changed enough to notice
time . Sleep ( 2 * time . Second )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , build . WithDockerfile ( dockerfile ) )
2016-10-06 07:53:30 +00:00
out2 , _ = dockerCmd ( c , "run" , name , "ls" , "-le" , "/file" )
2015-03-04 17:14:58 +00:00
2016-10-06 07:53:30 +00:00
if out != out2 {
c . Fatalf ( "MTime changed:\nOrigin:%s\nNew:%s" , out , out2 )
2015-03-04 17:14:58 +00:00
}
// Now 'touch' the file and make sure the timestamp DID change this time
// Create a new fakeStorage instead of just using Add() to help windows
2017-01-16 10:30:14 +00:00
server = fakeStorage ( c , map [ string ] string {
2015-03-04 17:14:58 +00:00
"file" : "hello" ,
} )
defer server . Close ( )
2015-03-09 23:56:51 +00:00
dockerfile = fmt . Sprintf ( dFmt , server . URL ( ) )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , build . WithDockerfile ( dockerfile ) )
2016-10-06 07:53:30 +00:00
out2 , _ = dockerCmd ( c , "run" , name , "ls" , "-le" , "/file" )
2015-03-04 17:14:58 +00:00
2016-10-06 07:53:30 +00:00
if out == out2 {
c . Fatalf ( "MTime didn't change:\nOrigin:%s\nNew:%s" , out , out2 )
2015-03-04 17:14:58 +00:00
}
}
2016-10-26 23:26:31 +00:00
// Regression for https://github.com/docker/docker/pull/27805
// Makes sure that we don't use the cache if the contents of
// a file in a subfolder of the context is modified and we re-build.
func ( s * DockerSuite ) TestBuildModifyFileInFolder ( c * check . C ) {
name := "testbuildmodifyfileinfolder"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , ` FROM busybox
2016-10-26 23:26:31 +00:00
RUN [ "mkdir" , "/test" ]
ADD folder / file / test / changetarget ` ,
map [ string ] string { } )
defer ctx . Close ( )
if err := ctx . Add ( "folder/file" , "first" ) ; err != nil {
c . Fatal ( err )
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2016-10-26 23:26:31 +00:00
if err := ctx . Add ( "folder/file" , "second" ) ; err != nil {
c . Fatal ( err )
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name )
2016-10-26 23:26:31 +00:00
if id1 == id2 {
c . Fatal ( "cache was used even though file contents in folder was changed" )
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddSingleFileToRoot ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testaddimg" , withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
2014-09-22 14:23:20 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio / exists
ADD test_file /
RUN [ $ ( ls - l / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2015-03-04 02:40:16 +00:00
RUN [ $ ( ls - l / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ) ,
withFile ( "test_file" , "test1" ) ) )
2014-04-09 14:21:22 +00:00
}
2014-05-22 22:12:41 +00:00
// Issue #3960: "ADD src ." hangs
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddSingleFileToWorkdir ( c * check . C ) {
2014-09-22 14:51:42 +00:00
name := "testaddsinglefiletoworkdir"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , ` FROM busybox
2014-09-22 14:51:42 +00:00
ADD test_file . ` ,
map [ string ] string {
"test_file" : "test1" ,
} )
2014-11-20 17:38:41 +00:00
defer ctx . Close ( )
2015-04-27 17:29:48 +00:00
errChan := make ( chan error )
2014-09-22 14:51:42 +00:00
go func ( ) {
2017-01-16 10:30:14 +00:00
errChan <- buildImage ( name , withExternalBuildContext ( ctx ) ) . Error
2015-04-27 17:29:48 +00:00
close ( errChan )
2014-09-22 14:51:42 +00:00
} ( )
select {
2015-11-20 22:12:12 +00:00
case <- time . After ( 15 * time . Second ) :
2015-04-18 16:46:47 +00:00
c . Fatal ( "Build with adding to workdir timed out" )
2015-04-27 17:29:48 +00:00
case err := <- errChan :
c . Assert ( err , check . IsNil )
2014-05-22 22:12:41 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddSingleFileToExistDir ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testaddsinglefiletoexistdir" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-09-22 15:24:14 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
RUN chown - R dockerio . dockerio / exists
ADD test_file / exists /
RUN [ $ ( ls - l / | grep exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
RUN [ $ ( ls - l / exists / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists / exists_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` ) ,
withFile ( "test_file" , "test1" ) ) )
2014-04-09 14:21:22 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopyAddMultipleFiles ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , map [ string ] string {
2015-02-26 02:08:17 +00:00
"robots.txt" : "hello" ,
} )
defer server . Close ( )
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testcopymultiplefilestofile" , withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
2014-10-02 18:33:12 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
RUN chown - R dockerio . dockerio / exists
COPY test_file1 test_file2 / exists /
2015-02-26 02:08:17 +00:00
ADD test_file3 test_file4 % s / robots . txt / exists /
2014-10-02 18:33:12 +00:00
RUN [ $ ( ls - l / | grep exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
RUN [ $ ( ls - l / exists / test_file1 | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / exists / test_file2 | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / exists / test_file3 | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / exists / test_file4 | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / exists / robots . txt | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / exists / exists_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
2017-01-10 18:16:25 +00:00
` , server . URL ( ) ) ) ,
withFile ( "test_file1" , "test1" ) ,
withFile ( "test_file2" , "test2" ) ,
withFile ( "test_file3" , "test3" ) ,
withFile ( "test_file3" , "test3" ) ,
withFile ( "test_file4" , "test4" ) ) )
2016-03-13 04:05:45 +00:00
}
2017-01-10 18:16:25 +00:00
// These tests are mainly for user namespaces to verify that new directories
2016-03-13 04:05:45 +00:00
// are created as the remapped root uid/gid pair
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildUsernamespaceValidateRemappedRoot ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
testCases := [ ] string {
"ADD . /new_dir" ,
"COPY test_dir /new_dir" ,
"WORKDIR /new_dir" ,
2016-02-27 02:50:50 +00:00
}
2017-01-10 18:16:25 +00:00
name := "testbuildusernamespacevalidateremappedroot"
for _ , tc := range testCases {
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
% s
RUN [ $ ( ls - l / | grep new_dir | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ] ` , tc ) ) ,
withFile ( "test_dir/test_file" , "test file" ) ) )
2016-02-27 02:50:50 +00:00
2017-01-10 18:16:25 +00:00
dockerCmd ( c , "rmi" , name )
2016-03-08 15:40:30 +00:00
}
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildAddAndCopyFileWithWhitespace ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Not currently passing on Windows
2014-10-06 10:15:09 +00:00
name := "testaddfilewithwhitespace"
2017-01-10 18:16:25 +00:00
for _ , command := range [ ] string { "ADD" , "COPY" } {
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
2014-10-06 10:15:09 +00:00
RUN mkdir "/test dir"
RUN mkdir "/test_dir"
2017-01-10 18:16:25 +00:00
% s [ "test file1" , "/test_file1" ]
% s [ "test_file2" , "/test file2" ]
% s [ "test file3" , "/test file3" ]
% s [ "test dir/test_file4" , "/test_dir/test_file4" ]
% s [ "test_dir/test_file5" , "/test dir/test_file5" ]
% s [ "test dir/test_file6" , "/test dir/test_file6" ]
2014-10-06 10:15:09 +00:00
RUN [ $ ( cat "/test_file1" ) = ' test1 ' ]
RUN [ $ ( cat "/test file2" ) = ' test2 ' ]
RUN [ $ ( cat "/test file3" ) = ' test3 ' ]
RUN [ $ ( cat "/test_dir/test_file4" ) = ' test4 ' ]
RUN [ $ ( cat "/test dir/test_file5" ) = ' test5 ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( cat "/test dir/test_file6" ) = ' test6 ' ] ` , command , command , command , command , command , command ) ) ,
withFile ( "test file1" , "test1" ) ,
withFile ( "test_file2" , "test2" ) ,
withFile ( "test file3" , "test3" ) ,
withFile ( "test dir/test_file4" , "test4" ) ,
withFile ( "test_dir/test_file5" , "test5" ) ,
withFile ( "test dir/test_file6" , "test6" ) ,
) )
2014-10-06 10:15:09 +00:00
2017-01-10 18:16:25 +00:00
dockerCmd ( c , "rmi" , name )
2014-10-06 10:15:09 +00:00
}
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildCopyFileWithWhitespaceOnWindows ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
2017-01-13 16:23:28 +00:00
dockerfile := ` FROM ` + testEnv . MinimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
RUN mkdir "C:/test dir"
RUN mkdir "C:/test_dir"
2016-09-14 00:43:27 +00:00
COPY [ "test file1" , "/test_file1" ]
COPY [ "test_file2" , "/test file2" ]
COPY [ "test file3" , "/test file3" ]
COPY [ "test dir/test_file4" , "/test_dir/test_file4" ]
COPY [ "test_dir/test_file5" , "/test dir/test_file5" ]
COPY [ "test dir/test_file6" , "/test dir/test_file6" ]
RUN find "test1" "C:/test_file1"
RUN find "test2" "C:/test file2"
RUN find "test3" "C:/test file3"
RUN find "test4" "C:/test_dir/test_file4"
RUN find "test5" "C:/test dir/test_file5"
RUN find "test6" "C:/test dir/test_file6" `
name := "testcopyfilewithwhitespace"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( "test file1" , "test1" ) ,
withFile ( "test_file2" , "test2" ) ,
withFile ( "test file3" , "test3" ) ,
withFile ( "test dir/test_file4" , "test4" ) ,
withFile ( "test_dir/test_file5" , "test5" ) ,
withFile ( "test dir/test_file6" , "test6" ) ,
) )
2014-10-06 10:15:09 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopyWildcard ( c * check . C ) {
2014-09-22 13:41:02 +00:00
name := "testcopywildcard"
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , map [ string ] string {
2014-09-22 13:41:02 +00:00
"robots.txt" : "hello" ,
"index.html" : "world" ,
} )
defer server . Close ( )
2015-02-19 10:01:27 +00:00
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , fmt . Sprintf ( ` FROM busybox
2014-09-22 13:41:02 +00:00
COPY file * . txt / tmp /
RUN ls / tmp / file1 . txt / tmp / file2 . txt
2016-09-14 00:50:45 +00:00
RUN [ "mkdir" , "/tmp1" ]
2014-09-22 13:41:02 +00:00
COPY dir * / tmp1 /
RUN ls / tmp1 / dirt / tmp1 / nested_file / tmp1 / nested_dir / nest_nest_file
2016-09-14 00:50:45 +00:00
RUN [ "mkdir" , "/tmp2" ]
2014-09-22 13:41:02 +00:00
ADD dir / * dir % s / robots . txt / tmp2 /
RUN ls / tmp2 / nest_nest_file / tmp2 / robots . txt
2015-02-19 10:01:27 +00:00
` , server . URL ( ) ) ,
2014-09-22 13:41:02 +00:00
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test2" ,
"dir/nested_file" : "nested file" ,
"dir/nested_dir/nest_nest_file" : "2 times nested" ,
"dirt" : "dirty" ,
} )
2015-04-10 19:39:42 +00:00
defer ctx . Close ( )
2014-09-22 13:41:02 +00:00
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2014-09-22 13:41:02 +00:00
// Now make sure we use a cache the 2nd time
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name )
2014-09-22 13:41:02 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "didn't use the cache" )
2014-09-22 13:41:02 +00:00
}
}
2015-04-10 19:39:42 +00:00
func ( s * DockerSuite ) TestBuildCopyWildcardInName ( c * check . C ) {
2017-01-10 18:16:25 +00:00
// Run this only on Linux
// Below is the original comment (that I don't agree with — vdemeester)
// Normally we would do c.Fatal(err) here but given that
// the odds of this failing are so rare, it must be because
// the OS we're running the client on doesn't support * in
// filenames (like windows). So, instead of failing the test
// just let it pass. Then we don't need to explicitly
// say which OSs this works on or not.
2017-01-20 15:09:17 +00:00
testRequires ( c , DaemonIsLinux , UnixCli )
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testcopywildcardinname" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2015-04-10 19:39:42 +00:00
COPY * . txt / tmp /
RUN [ "$(cat /tmp/\*.txt)" = ' hi there ' ]
2017-01-10 18:16:25 +00:00
` ) ,
withFile ( "*.txt" , "hi there" ) ,
) )
2015-04-10 19:39:42 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopyWildcardCache ( c * check . C ) {
2014-09-22 13:41:02 +00:00
name := "testcopywildcardcache"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , ` FROM busybox
2014-09-29 20:35:09 +00:00
COPY file1 . txt / tmp / ` ,
2014-09-22 13:41:02 +00:00
map [ string ] string {
"file1.txt" : "test1" ,
} )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2014-09-22 13:41:02 +00:00
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2014-09-22 13:41:02 +00:00
2014-09-29 20:35:09 +00:00
// Now make sure we use a cache the 2nd time even with wild cards.
// Use the same context so the file is the same and the checksum will match
ctx . Add ( "Dockerfile" , ` FROM busybox
COPY file * . txt / tmp / ` )
2014-09-22 13:41:02 +00:00
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name )
2014-09-22 13:41:02 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "didn't use the cache" )
2014-09-22 13:41:02 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddSingleFileToNonExistingDir ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testaddsinglefiletononexistingdir" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-09-22 15:41:13 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio / exists
ADD test_file / test_dir /
RUN [ $ ( ls - l / | grep test_dir | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` ) ,
withFile ( "test_file" , "test1" ) ) )
2014-04-09 14:21:22 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddDirContentToRoot ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testadddircontenttoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-09-22 16:47:01 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio exists
ADD test_dir /
RUN [ $ ( ls - l / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` ) ,
withFile ( "test_dir/test_file" , "test1" ) ) )
2014-04-09 14:21:22 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddDirContentToExistingDir ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testadddircontenttoexistingdir" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-09-22 17:21:39 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
RUN chown - R dockerio . dockerio / exists
ADD test_dir / / exists /
RUN [ $ ( ls - l / | grep exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
RUN [ $ ( ls - l / exists / exists_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ] ` ) ,
withFile ( "test_dir/test_file" , "test1" ) ) )
2014-04-09 14:21:22 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddWholeDirToRoot ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testaddwholedirtoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
2014-09-22 17:36:43 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio exists
ADD test_dir / test_dir
RUN [ $ ( ls - l / | grep test_dir | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / | grep test_dir | awk ' { print $ 1 } ' ) = ' drwxr - xr - x ' ]
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2015-03-04 02:40:16 +00:00
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ) ,
withFile ( "test_dir/test_file" , "test1" ) ) )
2014-04-09 14:21:22 +00:00
}
2017-01-10 18:16:25 +00:00
// Testing #5941 : Having an etc directory in context conflicts with the /etc/mtab
func ( s * DockerSuite ) TestBuildAddOrCopyEtcToRootShouldNotConflict ( c * check . C ) {
buildImageSuccessfully ( c , "testaddetctoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM ` + minimalBaseImage ( ) + `
ADD . / ` ) ,
withFile ( "etc/test_file" , "test1" ) ) )
buildImageSuccessfully ( c , "testcopyetctoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM ` + minimalBaseImage ( ) + `
COPY . / ` ) ,
withFile ( "etc/test_file" , "test1" ) ) )
2014-05-20 20:39:46 +00:00
}
2017-01-10 18:16:25 +00:00
// Testing #9401 : Losing setuid flag after a ADD
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddPreservesFilesSpecialBits ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testaddetctoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-12-03 02:45:07 +00:00
ADD suidbin / usr / bin / suidbin
RUN chmod 4755 / usr / bin / suidbin
RUN [ $ ( ls - l / usr / bin / suidbin | awk ' { print $ 1 } ' ) = ' - rwsr - xr - x ' ]
ADD . / data / /
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / usr / bin / suidbin | awk ' { print $ 1 } ' ) = ' - rwsr - xr - x ' ] ` ) ,
withFile ( "suidbin" , "suidbin" ) ,
withFile ( "/data/usr/test_file" , "test1" ) ) )
2014-12-03 02:45:07 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopySingleFileToRoot ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testcopysinglefiletoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
2014-10-14 17:07:04 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio / exists
COPY test_file /
RUN [ $ ( ls - l / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2015-03-04 02:40:16 +00:00
RUN [ $ ( ls - l / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ) ,
withFile ( "test_file" , "test1" ) ) )
2014-05-28 17:53:16 +00:00
}
// Issue #3960: "ADD src ." hangs - adapted for COPY
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopySingleFileToWorkdir ( c * check . C ) {
2014-10-14 17:12:11 +00:00
name := "testcopysinglefiletoworkdir"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , ` FROM busybox
2014-10-14 17:12:11 +00:00
COPY test_file . ` ,
map [ string ] string {
"test_file" : "test1" ,
} )
2014-11-20 17:38:41 +00:00
defer ctx . Close ( )
2015-04-27 17:29:48 +00:00
errChan := make ( chan error )
2014-10-14 17:12:11 +00:00
go func ( ) {
2017-01-16 10:30:14 +00:00
errChan <- buildImage ( name , withExternalBuildContext ( ctx ) ) . Error
2015-04-27 17:29:48 +00:00
close ( errChan )
2014-10-14 17:12:11 +00:00
} ( )
select {
2015-11-20 22:12:12 +00:00
case <- time . After ( 15 * time . Second ) :
2015-04-18 16:46:47 +00:00
c . Fatal ( "Build with adding to workdir timed out" )
2015-04-27 17:29:48 +00:00
case err := <- errChan :
c . Assert ( err , check . IsNil )
2014-05-28 17:53:16 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopySingleFileToExistDir ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testcopysinglefiletoexistdir" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-10-14 17:15:45 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
RUN chown - R dockerio . dockerio / exists
COPY test_file / exists /
RUN [ $ ( ls - l / | grep exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
RUN [ $ ( ls - l / exists / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists / exists_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` ) ,
withFile ( "test_file" , "test1" ) ) )
2014-05-28 17:53:16 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopySingleFileToNonExistDir ( c * check . C ) {
2017-01-10 18:16:25 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific
buildImageSuccessfully ( c , "testcopysinglefiletononexistdir" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-10-14 17:19:45 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio / exists
COPY test_file / test_dir /
RUN [ $ ( ls - l / | grep test_dir | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` ) ,
withFile ( "test_file" , "test1" ) ) )
2014-05-28 17:53:16 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopyDirContentToRoot ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testcopydircontenttoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-10-14 17:22:06 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio exists
COPY test_dir /
RUN [ $ ( ls - l / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` ) ,
withFile ( "test_dir/test_file" , "test1" ) ) )
2014-05-28 17:53:16 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopyDirContentToExistDir ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testcopydircontenttoexistdir" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-10-14 17:26:20 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
RUN chown - R dockerio . dockerio / exists
COPY test_dir / / exists /
RUN [ $ ( ls - l / | grep exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
RUN [ $ ( ls - l / exists / exists_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ] ` ) ,
withFile ( "test_dir/test_file" , "test1" ) ) )
2014-05-28 17:53:16 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCopyWholeDirToRoot ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Linux specific test
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testcopywholedirtoroot" , withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
2014-10-14 17:29:22 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN touch / exists
RUN chown dockerio . dockerio exists
COPY test_dir / test_dir
RUN [ $ ( ls - l / | grep test_dir | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
RUN [ $ ( ls - l / | grep test_dir | awk ' { print $ 1 } ' ) = ' drwxr - xr - x ' ]
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2015-03-04 02:40:16 +00:00
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
2017-01-10 18:16:25 +00:00
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ) ,
withFile ( "test_dir/test_file" , "test1" ) ) )
2014-05-28 17:53:16 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddBadLinks ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // Not currently working on Windows
dockerfile := `
FROM scratch
ADD links . tar /
ADD foo . txt / symlink /
`
targetFile := "foo.txt"
2014-11-27 20:14:15 +00:00
var (
name = "test-link-absolute"
)
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , nil )
2014-11-27 20:14:15 +00:00
defer ctx . Close ( )
tempDir , err := ioutil . TempDir ( "" , "test-link-absolute-temp-" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to create temporary directory: %s" , tempDir )
2014-11-27 20:14:15 +00:00
}
defer os . RemoveAll ( tempDir )
2015-02-18 07:20:20 +00:00
var symlinkTarget string
if runtime . GOOS == "windows" {
var driveLetter string
if abs , err := filepath . Abs ( tempDir ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-18 07:20:20 +00:00
} else {
driveLetter = abs [ : 1 ]
}
tempDirWithoutDrive := tempDir [ 2 : ]
symlinkTarget = fmt . Sprintf ( ` %s:\..\..\..\..\..\..\..\..\..\..\..\..%s ` , driveLetter , tempDirWithoutDrive )
} else {
symlinkTarget = fmt . Sprintf ( "/../../../../../../../../../../../..%s" , tempDir )
}
2014-11-27 20:14:15 +00:00
tarPath := filepath . Join ( ctx . Dir , "links.tar" )
nonExistingFile := filepath . Join ( tempDir , targetFile )
fooPath := filepath . Join ( ctx . Dir , targetFile )
tarOut , err := os . Create ( tarPath )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-27 20:14:15 +00:00
}
tarWriter := tar . NewWriter ( tarOut )
header := & tar . Header {
Name : "symlink" ,
Typeflag : tar . TypeSymlink ,
Linkname : symlinkTarget ,
Mode : 0755 ,
Uid : 0 ,
Gid : 0 ,
}
err = tarWriter . WriteHeader ( header )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-27 20:14:15 +00:00
}
tarWriter . Close ( )
tarOut . Close ( )
foo , err := os . Create ( fooPath )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-27 20:14:15 +00:00
}
defer foo . Close ( )
if _ , err := foo . WriteString ( "test" ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-27 20:14:15 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2014-11-27 20:14:15 +00:00
if _ , err := os . Stat ( nonExistingFile ) ; err == nil || err != nil && ! os . IsNotExist ( err ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "%s shouldn't have been written and it shouldn't exist" , nonExistingFile )
2014-11-27 20:14:15 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddBadLinksVolume ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux ) // ln not implemented on Windows busybox
2014-11-27 20:39:43 +00:00
const (
dockerfileTemplate = `
FROM busybox
RUN ln - s / . . / . . / . . / . . / . . / . . / . . / . . / % s / x
VOLUME / x
ADD foo . txt / x / `
targetFile = "foo.txt"
)
var (
name = "test-link-absolute-volume"
dockerfile = ""
)
tempDir , err := ioutil . TempDir ( "" , "test-link-absolute-volume-temp-" )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to create temporary directory: %s" , tempDir )
2014-11-27 20:39:43 +00:00
}
defer os . RemoveAll ( tempDir )
dockerfile = fmt . Sprintf ( dockerfileTemplate , tempDir )
nonExistingFile := filepath . Join ( tempDir , targetFile )
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , nil )
2014-11-27 20:39:43 +00:00
defer ctx . Close ( )
fooPath := filepath . Join ( ctx . Dir , targetFile )
foo , err := os . Create ( fooPath )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-27 20:39:43 +00:00
}
defer foo . Close ( )
if _ , err := foo . WriteString ( "test" ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-27 20:39:43 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2014-11-27 20:39:43 +00:00
if _ , err := os . Stat ( nonExistingFile ) ; err == nil || err != nil && ! os . IsNotExist ( err ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "%s shouldn't have been written and it shouldn't exist" , nonExistingFile )
2014-11-27 20:39:43 +00:00
}
}
2014-05-13 18:49:12 +00:00
// Issue #5270 - ensure we throw a better error than "unexpected EOF"
// when we can't access files in the context.
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildWithInaccessibleFilesInContext ( c * check . C ) {
2016-01-25 23:58:03 +00:00
testRequires ( c , DaemonIsLinux , UnixCli ) // test uses chown/chmod: not available on windows
2015-02-20 09:37:27 +00:00
2014-05-13 18:49:12 +00:00
{
2014-09-24 12:42:17 +00:00
name := "testbuildinaccessiblefiles"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , "FROM scratch\nADD . /foo/" , map [ string ] string { "fileWithoutReadAccess" : "foo" } )
2014-09-24 12:42:17 +00:00
defer ctx . Close ( )
2014-05-13 18:49:12 +00:00
// This is used to ensure we detect inaccessible files early during build in the cli client
2014-09-24 12:42:17 +00:00
pathToFileWithoutReadAccess := filepath . Join ( ctx . Dir , "fileWithoutReadAccess" )
2014-05-13 18:49:12 +00:00
2017-01-16 10:30:14 +00:00
if err := os . Chown ( pathToFileWithoutReadAccess , 0 , 0 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to chown file to root: %s" , err )
2014-10-14 20:51:12 +00:00
}
2017-01-16 10:30:14 +00:00
if err := os . Chmod ( pathToFileWithoutReadAccess , 0700 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to chmod file to 700: %s" , err )
2014-10-14 20:51:12 +00:00
}
2017-01-10 18:16:25 +00:00
result := icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { "su" , "unprivilegeduser" , "-c" , fmt . Sprintf ( "%s build -t %s ." , dockerBinary , name ) } ,
Dir : ctx . Dir ,
} )
if result . Error == nil {
c . Fatalf ( "build should have failed: %s %s" , result . Error , result . Combined ( ) )
2014-05-13 18:49:12 +00:00
}
// check if we've detected the failure before we started building
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "no permission to read from " ) {
c . Fatalf ( "output should've contained the string: no permission to read from but contained: %s" , result . Combined ( ) )
2014-05-13 18:49:12 +00:00
}
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "Error checking context" ) {
2015-05-30 02:38:56 +00:00
c . Fatalf ( "output should've contained the string: Error checking context" )
2014-05-13 18:49:12 +00:00
}
}
{
2014-09-24 12:42:17 +00:00
name := "testbuildinaccessibledirectory"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , "FROM scratch\nADD . /foo/" , map [ string ] string { "directoryWeCantStat/bar" : "foo" } )
2014-09-24 12:42:17 +00:00
defer ctx . Close ( )
2014-05-13 18:49:12 +00:00
// This is used to ensure we detect inaccessible directories early during build in the cli client
2014-09-24 12:42:17 +00:00
pathToDirectoryWithoutReadAccess := filepath . Join ( ctx . Dir , "directoryWeCantStat" )
2014-05-13 18:49:12 +00:00
pathToFileInDirectoryWithoutReadAccess := filepath . Join ( pathToDirectoryWithoutReadAccess , "bar" )
2017-01-16 10:30:14 +00:00
if err := os . Chown ( pathToDirectoryWithoutReadAccess , 0 , 0 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to chown directory to root: %s" , err )
2014-10-14 20:51:12 +00:00
}
2017-01-16 10:30:14 +00:00
if err := os . Chmod ( pathToDirectoryWithoutReadAccess , 0444 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to chmod directory to 444: %s" , err )
2014-10-14 20:51:12 +00:00
}
2017-01-16 10:30:14 +00:00
if err := os . Chmod ( pathToFileInDirectoryWithoutReadAccess , 0700 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to chmod file to 700: %s" , err )
2014-10-14 20:51:12 +00:00
}
2014-05-13 18:49:12 +00:00
2017-01-10 18:16:25 +00:00
result := icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { "su" , "unprivilegeduser" , "-c" , fmt . Sprintf ( "%s build -t %s ." , dockerBinary , name ) } ,
Dir : ctx . Dir ,
} )
if result . Error == nil {
c . Fatalf ( "build should have failed: %s %s" , result . Error , result . Combined ( ) )
2014-05-13 18:49:12 +00:00
}
// check if we've detected the failure before we started building
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "can't stat" ) {
c . Fatalf ( "output should've contained the string: can't access %s" , result . Combined ( ) )
2014-05-13 18:49:12 +00:00
}
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "Error checking context" ) {
c . Fatalf ( "output should've contained the string: Error checking context\ngot:%s" , result . Combined ( ) )
2014-05-13 18:49:12 +00:00
}
}
{
2014-09-24 12:42:17 +00:00
name := "testlinksok"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , "FROM scratch\nADD . /foo/" , nil )
2014-09-24 12:42:17 +00:00
defer ctx . Close ( )
2014-11-17 16:05:49 +00:00
target := "../../../../../../../../../../../../../../../../../../../azA"
if err := os . Symlink ( filepath . Join ( ctx . Dir , "g" ) , target ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-09-24 12:42:17 +00:00
}
2014-11-17 16:05:49 +00:00
defer os . Remove ( target )
2014-05-13 18:49:12 +00:00
// This is used to ensure we don't follow links when checking if everything in the context is accessible
// This test doesn't require that we run commands as an unprivileged user
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2014-07-07 12:23:07 +00:00
}
{
2014-09-24 12:42:17 +00:00
name := "testbuildignoredinaccessible"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , "FROM scratch\nADD . /foo/" ,
2014-09-24 12:42:17 +00:00
map [ string ] string {
"directoryWeCantStat/bar" : "foo" ,
".dockerignore" : "directoryWeCantStat" ,
} )
defer ctx . Close ( )
2014-07-07 12:23:07 +00:00
// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
2014-09-24 12:42:17 +00:00
pathToDirectoryWithoutReadAccess := filepath . Join ( ctx . Dir , "directoryWeCantStat" )
2014-07-07 12:23:07 +00:00
pathToFileInDirectoryWithoutReadAccess := filepath . Join ( pathToDirectoryWithoutReadAccess , "bar" )
2017-01-16 10:30:14 +00:00
if err := os . Chown ( pathToDirectoryWithoutReadAccess , 0 , 0 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to chown directory to root: %s" , err )
2014-10-14 20:51:12 +00:00
}
2017-01-16 10:30:14 +00:00
if err := os . Chmod ( pathToDirectoryWithoutReadAccess , 0444 ) ; err != nil {
2016-08-04 12:14:15 +00:00
c . Fatalf ( "failed to chmod directory to 444: %s" , err )
2014-10-14 20:51:12 +00:00
}
2017-01-16 10:30:14 +00:00
if err := os . Chmod ( pathToFileInDirectoryWithoutReadAccess , 0700 ) ; err != nil {
2016-08-04 12:14:15 +00:00
c . Fatalf ( "failed to chmod file to 700: %s" , err )
2014-10-14 20:51:12 +00:00
}
2014-07-07 12:23:07 +00:00
2016-08-03 16:20:46 +00:00
result := icmd . RunCmd ( icmd . Cmd {
Dir : ctx . Dir ,
Command : [ ] string { "su" , "unprivilegeduser" , "-c" ,
fmt . Sprintf ( "%s build -t %s ." , dockerBinary , name ) } ,
} )
result . Assert ( c , icmd . Expected { } )
2014-05-13 18:49:12 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildForceRm ( c * check . C ) {
2017-01-16 15:39:12 +00:00
containerCountBefore := getContainerCount ( c )
2014-09-24 08:29:27 +00:00
name := "testbuildforcerm"
2016-01-28 20:40:52 +00:00
2017-03-23 17:35:22 +00:00
buildImage ( name , cli . WithFlags ( "--force-rm" ) , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "Dockerfile" , ` FROM ` + minimalBaseImage ( ) + `
2016-01-28 20:40:52 +00:00
RUN true
2017-01-10 18:16:25 +00:00
RUN thiswillfail ` ) ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2014-05-19 16:46:25 +00:00
2017-01-16 15:39:12 +00:00
containerCountAfter := getContainerCount ( c )
2014-05-19 16:46:25 +00:00
if containerCountBefore != containerCountAfter {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "--force-rm shouldn't have left containers behind" )
2014-05-19 16:46:25 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildRm ( c * check . C ) {
2014-09-24 09:15:55 +00:00
name := "testbuildrm"
2016-01-28 20:40:52 +00:00
2017-01-10 18:16:25 +00:00
testCases := [ ] struct {
buildflags [ ] string
shouldLeftContainerBehind bool
} {
// Default case (i.e. --rm=true)
{
buildflags : [ ] string { } ,
shouldLeftContainerBehind : false ,
} ,
{
buildflags : [ ] string { "--rm" } ,
shouldLeftContainerBehind : false ,
} ,
{
buildflags : [ ] string { "--rm=false" } ,
shouldLeftContainerBehind : true ,
} ,
2014-05-19 18:21:25 +00:00
}
2017-01-10 18:16:25 +00:00
for _ , tc := range testCases {
2017-01-16 15:39:12 +00:00
containerCountBefore := getContainerCount ( c )
2014-05-19 18:21:25 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( tc . buildflags ... ) , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
RUN echo hello world ` ) )
2014-05-19 18:21:25 +00:00
2017-01-16 15:39:12 +00:00
containerCountAfter := getContainerCount ( c )
2017-01-10 18:16:25 +00:00
if tc . shouldLeftContainerBehind {
if containerCountBefore == containerCountAfter {
c . Fatalf ( "flags %v should have left containers behind" , tc . buildflags )
}
} else {
if containerCountBefore != containerCountAfter {
c . Fatalf ( "flags %v shouldn't have left containers behind" , tc . buildflags )
}
2014-05-19 18:21:25 +00:00
}
2017-01-10 18:16:25 +00:00
dockerCmd ( c , "rmi" , name )
2014-05-19 18:21:25 +00:00
}
}
2014-06-17 06:04:25 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildWithVolumes ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // Invalid volume paths on Windows
2014-07-08 20:27:58 +00:00
var (
result map [ string ] map [ string ] struct { }
name = "testbuildvolumes"
emptyMap = make ( map [ string ] struct { } )
2014-09-11 13:27:51 +00:00
expected = map [ string ] map [ string ] struct { } {
"/test1" : emptyMap ,
"/test2" : emptyMap ,
"/test3" : emptyMap ,
"/test4" : emptyMap ,
"/test5" : emptyMap ,
"/test6" : emptyMap ,
"[/test7" : emptyMap ,
"/test8]" : emptyMap ,
}
2014-07-08 20:27:58 +00:00
)
2017-01-10 18:16:25 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM scratch
2014-05-31 12:43:32 +00:00
VOLUME / test1
2014-09-11 13:27:51 +00:00
VOLUME / test2
VOLUME / test3 / test4
VOLUME [ "/test5" , "/test6" ]
VOLUME [ / test7 / test8 ]
2017-01-10 18:16:25 +00:00
` ) )
2014-07-08 20:27:58 +00:00
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.Volumes" , & result )
2014-07-08 20:27:58 +00:00
2014-12-04 01:52:06 +00:00
equal := reflect . DeepEqual ( & result , & expected )
2014-07-08 20:27:58 +00:00
if ! equal {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Volumes %s, expected %s" , result , expected )
2014-07-08 20:27:58 +00:00
}
2014-05-22 19:16:27 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildMaintainer ( c * check . C ) {
2014-05-31 12:43:32 +00:00
name := "testbuildmaintainer"
2016-01-28 20:40:52 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
MAINTAINER dockerio ` ) )
2014-05-31 12:43:32 +00:00
expected := "dockerio"
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Author" )
2014-05-31 12:43:32 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Maintainer %s, expected %s" , res , expected )
2014-05-31 12:43:32 +00:00
}
2014-05-25 18:26:50 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildUser ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-05-31 12:43:32 +00:00
name := "testbuilduser"
expected := "dockerio"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-05-25 18:28:14 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
USER dockerio
2017-01-10 18:16:25 +00:00
RUN [ $ ( whoami ) = ' dockerio ' ] ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.User" )
2014-05-31 12:43:32 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "User %s, expected %s" , res , expected )
2014-05-31 12:43:32 +00:00
}
2014-05-25 18:28:14 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildRelativeWorkdir ( c * check . C ) {
2014-05-31 12:43:32 +00:00
name := "testbuildrelativeworkdir"
2016-01-28 20:40:52 +00:00
var (
expected1 string
expected2 string
expected3 string
expected4 string
expectedFinal string
)
2016-04-20 03:55:30 +00:00
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-04-18 17:11:37 +00:00
expected1 = ` C:/ `
2016-01-28 20:40:52 +00:00
expected2 = ` C:/test1 `
expected3 = ` C:/test2 `
expected4 = ` C:/test2/test3 `
2016-04-20 03:55:30 +00:00
expectedFinal = ` C:\test2\test3 ` // Note inspect is going to return Windows paths, as it's not in busybox
2016-01-28 20:40:52 +00:00
} else {
expected1 = ` / `
expected2 = ` /test1 `
expected3 = ` /test2 `
expected4 = ` /test2/test3 `
expectedFinal = ` /test2/test3 `
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2016-04-18 17:11:37 +00:00
RUN sh - c "[ " $ PWD " = " ` +expected1+ ` " ]"
2014-05-25 18:41:47 +00:00
WORKDIR test1
2016-04-18 17:11:37 +00:00
RUN sh - c "[ " $ PWD " = " ` +expected2+ ` " ]"
2014-05-25 18:41:47 +00:00
WORKDIR / test2
2016-04-18 17:11:37 +00:00
RUN sh - c "[ " $ PWD " = " ` +expected3+ ` " ]"
2014-05-25 18:41:47 +00:00
WORKDIR test3
2017-01-10 18:16:25 +00:00
RUN sh - c "[ " $ PWD " = " ` +expected4+ ` " ]" ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.WorkingDir" )
2016-01-28 20:40:52 +00:00
if res != expectedFinal {
c . Fatalf ( "Workdir %s, expected %s" , res , expectedFinal )
2014-05-31 12:43:32 +00:00
}
2014-05-25 18:41:47 +00:00
}
2016-05-03 01:33:59 +00:00
// #22181 Regression test. Single end-to-end test of using
// Windows semantics. Most path handling verifications are in unit tests
2016-04-20 03:55:30 +00:00
func ( s * DockerSuite ) TestBuildWindowsWorkdirProcessing ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "testbuildwindowsworkdirprocessing" , build . WithDockerfile ( ` FROM busybox
2016-05-03 01:33:59 +00:00
WORKDIR C : \ \ foo
2016-04-20 03:55:30 +00:00
WORKDIR bar
RUN sh - c "[ " $ PWD " = " C : / foo / bar " ]"
2017-01-10 18:16:25 +00:00
` ) )
2016-04-20 03:55:30 +00:00
}
2016-05-03 01:33:59 +00:00
// #22181 Regression test. Most paths handling verifications are in unit test.
// One functional test for end-to-end
2016-04-20 03:55:30 +00:00
func ( s * DockerSuite ) TestBuildWindowsAddCopyPathProcessing ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
2016-11-16 21:38:45 +00:00
// TODO Windows (@jhowardmsft). Needs a follow-up PR to 22181 to
// support backslash such as .\\ being equivalent to ./ and c:\\ being
// equivalent to c:/. This is not currently (nor ever has been) supported
// by docker on the Windows platform.
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testbuildwindowsaddcopypathprocessing" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2016-05-03 01:33:59 +00:00
# No trailing slash on COPY / ADD
2016-04-20 03:55:30 +00:00
# Results in dir being changed to a file
WORKDIR / wc1
COPY wc1 c : / wc1
WORKDIR / wc2
ADD wc2 c : / wc2
WORKDIR c : /
2016-11-16 23:02:27 +00:00
RUN sh - c "[ $(cat c:/wc1/wc1) = 'hellowc1' ]"
RUN sh - c "[ $(cat c:/wc2/wc2) = 'worldwc2' ]"
2016-04-20 03:55:30 +00:00
2016-08-04 16:17:37 +00:00
# Trailing slash on COPY / ADD , Windows - style path .
2016-04-20 03:55:30 +00:00
WORKDIR / wd1
COPY wd1 c : / wd1 /
WORKDIR / wd2
ADD wd2 c : / wd2 /
RUN sh - c "[ $(cat c:/wd1/wd1) = 'hellowd1' ]"
RUN sh - c "[ $(cat c:/wd2/wd2) = 'worldwd2' ]"
2017-01-10 18:16:25 +00:00
` ) ,
withFile ( "wc1" , "hellowc1" ) ,
withFile ( "wc2" , "worldwc2" ) ,
withFile ( "wd1" , "hellowd1" ) ,
withFile ( "wd2" , "worldwd2" ) ,
) )
2016-04-20 03:55:30 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildWorkdirWithEnvVariables ( c * check . C ) {
2014-07-15 17:17:20 +00:00
name := "testbuildworkdirwithenvvariables"
2016-01-28 20:40:52 +00:00
var expected string
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-04-20 03:55:30 +00:00
expected = ` C:\test1\test2 `
2016-01-28 20:40:52 +00:00
} else {
expected = ` /test1/test2 `
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-07-15 17:17:20 +00:00
ENV DIRPATH / test1
ENV SUBDIRNAME test2
WORKDIR $ DIRPATH
2017-01-10 18:16:25 +00:00
WORKDIR $ SUBDIRNAME / $ MISSING_VAR ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.WorkingDir" )
2014-07-15 17:17:20 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Workdir %s, expected %s" , res , expected )
2014-07-15 17:17:20 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildRelativeCopy ( c * check . C ) {
2015-09-18 17:41:12 +00:00
// cat /test1/test2/foo gets permission denied for the user
testRequires ( c , NotUserNamespace )
2016-01-28 20:40:52 +00:00
var expected string
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-01-28 20:40:52 +00:00
expected = ` C:/test1/test2 `
} else {
expected = ` /test1/test2 `
}
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "testbuildrelativecopy" , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-12-12 18:32:11 +00:00
WORKDIR / test1
WORKDIR test2
2017-01-10 18:16:25 +00:00
RUN sh - c "[ " $ PWD " = '`+expected+`' ]"
2014-12-12 18:32:11 +00:00
COPY foo . /
2016-01-28 20:40:52 +00:00
RUN sh - c "[ $(cat /test1/test2/foo) = 'hello' ]"
2014-12-12 18:32:11 +00:00
ADD foo . / bar / baz
2016-01-28 20:40:52 +00:00
RUN sh - c "[ $(cat /test1/test2/bar/baz) = 'hello' ]"
2014-12-12 18:32:11 +00:00
COPY foo . / bar / baz2
2016-01-28 20:40:52 +00:00
RUN sh - c "[ $(cat /test1/test2/bar/baz2) = 'hello' ]"
2014-12-12 18:32:11 +00:00
WORKDIR . .
COPY foo . /
2016-01-28 20:40:52 +00:00
RUN sh - c "[ $(cat /test1/foo) = 'hello' ]"
2014-12-12 18:32:11 +00:00
COPY foo / test3 /
2016-01-28 20:40:52 +00:00
RUN sh - c "[ $(cat /test3/foo) = 'hello' ]"
2014-12-12 18:32:11 +00:00
WORKDIR / test4
COPY . .
2016-01-28 20:40:52 +00:00
RUN sh - c "[ $(cat /test4/foo) = 'hello' ]"
2014-12-12 18:32:11 +00:00
WORKDIR / test5 / test6
COPY foo . . /
2016-01-28 20:40:52 +00:00
RUN sh - c "[ $(cat /test5/foo) = 'hello' ]"
2017-01-10 18:16:25 +00:00
` ) ,
withFile ( "foo" , "hello" ) ,
) )
2014-12-12 18:32:11 +00:00
}
2016-08-01 16:38:05 +00:00
func ( s * DockerSuite ) TestBuildBlankName ( c * check . C ) {
name := "testbuildblankname"
2017-01-10 18:16:25 +00:00
testCases := [ ] struct {
expression string
expectedStderr string
} {
{
expression : "ENV =" ,
expectedStderr : "ENV names can not be blank" ,
} ,
{
expression : "LABEL =" ,
expectedStderr : "LABEL names can not be blank" ,
} ,
{
expression : "ARG =foo" ,
expectedStderr : "ARG names can not be blank" ,
} ,
2016-08-01 16:38:05 +00:00
}
2017-01-10 18:16:25 +00:00
for _ , tc := range testCases {
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( fmt . Sprintf ( ` FROM busybox
2017-01-10 18:16:25 +00:00
% s ` , tc . expression ) ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : tc . expectedStderr ,
} )
2016-08-01 16:38:05 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnv ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // ENV expansion is different in Windows
2014-05-31 12:43:32 +00:00
name := "testbuildenv"
2014-08-13 10:07:41 +00:00
expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-08-13 10:07:41 +00:00
ENV PATH / test : $ PATH
2017-01-10 18:16:25 +00:00
ENV PORT 2375
RUN [ $ ( env | grep PORT ) = ' PORT = 2375 ' ] ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Env" )
2014-05-31 12:43:32 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Env %s, expected %s" , res , expected )
2014-05-31 12:43:32 +00:00
}
2014-05-26 19:09:33 +00:00
}
2016-01-04 03:45:06 +00:00
func ( s * DockerSuite ) TestBuildPATH ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // ENV expansion is different in Windows
2016-01-04 03:45:06 +00:00
defPath := "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
2017-01-10 18:16:25 +00:00
fn := func ( dockerfile string , expected string ) {
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "testbldpath" , build . WithDockerfile ( dockerfile ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , "testbldpath" , "Config.Env" )
2017-01-10 18:16:25 +00:00
if res != expected {
c . Fatalf ( "Env %q, expected %q for dockerfile:%q" , res , expected , dockerfile )
2016-01-04 03:45:06 +00:00
}
}
tests := [ ] struct { dockerfile , exp string } {
{ "FROM scratch\nMAINTAINER me" , "[PATH=" + defPath + "]" } ,
{ "FROM busybox\nMAINTAINER me" , "[PATH=" + defPath + "]" } ,
{ "FROM scratch\nENV FOO=bar" , "[PATH=" + defPath + " FOO=bar]" } ,
{ "FROM busybox\nENV FOO=bar" , "[PATH=" + defPath + " FOO=bar]" } ,
{ "FROM scratch\nENV PATH=/test" , "[PATH=/test]" } ,
{ "FROM busybox\nENV PATH=/test" , "[PATH=/test]" } ,
{ "FROM scratch\nENV PATH=''" , "[PATH=]" } ,
{ "FROM busybox\nENV PATH=''" , "[PATH=]" } ,
}
for _ , test := range tests {
fn ( test . dockerfile , test . exp )
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildContextCleanup ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-19 04:06:23 +00:00
2014-09-02 14:35:25 +00:00
name := "testbuildcontextcleanup"
2017-01-13 16:23:28 +00:00
entries , err := ioutil . ReadDir ( filepath . Join ( testEnv . DockerBasePath ( ) , "tmp" ) )
2014-09-02 14:35:25 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-02 14:35:25 +00:00
}
2017-01-10 18:16:25 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ "/bin/echo" ] ` ) )
2017-01-13 16:23:28 +00:00
entriesFinal , err := ioutil . ReadDir ( filepath . Join ( testEnv . DockerBasePath ( ) , "tmp" ) )
2014-09-02 14:35:25 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-02 14:35:25 +00:00
}
2016-12-30 17:23:00 +00:00
if err = testutil . CompareDirectoryEntries ( entries , entriesFinal ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "context should have been deleted, but wasn't" )
2014-09-02 14:35:25 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildContextCleanupFailedBuild ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-19 04:06:23 +00:00
2014-09-15 13:01:23 +00:00
name := "testbuildcontextcleanup"
2017-01-13 16:23:28 +00:00
entries , err := ioutil . ReadDir ( filepath . Join ( testEnv . DockerBasePath ( ) , "tmp" ) )
2014-09-15 13:01:23 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-15 13:01:23 +00:00
}
2017-01-10 18:16:25 +00:00
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
RUN / non / existing / command ` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2017-01-13 16:23:28 +00:00
entriesFinal , err := ioutil . ReadDir ( filepath . Join ( testEnv . DockerBasePath ( ) , "tmp" ) )
2014-09-15 13:01:23 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-15 13:01:23 +00:00
}
2016-12-30 17:23:00 +00:00
if err = testutil . CompareDirectoryEntries ( entries , entriesFinal ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "context should have been deleted, but wasn't" )
2014-09-15 13:01:23 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCmd ( c * check . C ) {
2014-05-31 12:43:32 +00:00
name := "testbuildcmd"
2016-02-29 11:28:37 +00:00
expected := "[/bin/echo Hello World]"
2017-01-10 18:16:25 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
CMD [ "/bin/echo" , "Hello World" ] ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Cmd" )
2014-05-31 12:43:32 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Cmd %s, expected %s" , res , expected )
2014-05-31 12:43:32 +00:00
}
2014-05-26 19:15:40 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildExpose ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // Expose not implemented on Windows
2014-05-31 12:43:32 +00:00
name := "testbuildexpose"
2015-03-26 19:43:00 +00:00
expected := "map[2375/tcp:{}]"
2017-01-10 18:16:25 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM scratch
2017-01-10 18:16:25 +00:00
EXPOSE 2375 ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.ExposedPorts" )
2014-05-31 12:43:32 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Exposed ports %s, expected %s" , res , expected )
2014-05-31 12:43:32 +00:00
}
2014-05-26 19:23:46 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildExposeMorePorts ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // Expose not implemented on Windows
2014-11-13 03:14:15 +00:00
// start building docker file with a large number of ports
portList := make ( [ ] string , 50 )
line := make ( [ ] string , 100 )
expectedPorts := make ( [ ] int , len ( portList ) * len ( line ) )
for i := 0 ; i < len ( portList ) ; i ++ {
for j := 0 ; j < len ( line ) ; j ++ {
p := i * len ( line ) + j + 1
line [ j ] = strconv . Itoa ( p )
expectedPorts [ p - 1 ] = p
}
if i == len ( portList ) - 1 {
portList [ i ] = strings . Join ( line , " " )
} else {
portList [ i ] = strings . Join ( line , " " ) + ` \ `
}
}
dockerfile := ` FROM scratch
EXPOSE { { range . } } { { . } }
{ { end } } `
tmpl := template . Must ( template . New ( "dockerfile" ) . Parse ( dockerfile ) )
buf := bytes . NewBuffer ( nil )
tmpl . Execute ( buf , portList )
name := "testbuildexpose"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( buf . String ( ) ) )
2014-11-13 03:14:15 +00:00
// check if all the ports are saved inside Config.ExposedPorts
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "Config.ExposedPorts" )
2014-11-13 03:14:15 +00:00
var exposedPorts map [ string ] interface { }
if err := json . Unmarshal ( [ ] byte ( res ) , & exposedPorts ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-11-13 03:14:15 +00:00
}
for _ , p := range expectedPorts {
ep := fmt . Sprintf ( "%d/tcp" , p )
if _ , ok := exposedPorts [ ep ] ; ! ok {
2015-04-18 16:46:47 +00:00
c . Errorf ( "Port(%s) is not exposed" , ep )
2014-11-13 03:14:15 +00:00
} else {
delete ( exposedPorts , ep )
}
}
if len ( exposedPorts ) != 0 {
2015-04-18 16:46:47 +00:00
c . Errorf ( "Unexpected extra exposed ports %v" , exposedPorts )
2014-11-13 03:14:15 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildExposeOrder ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // Expose not implemented on Windows
2014-11-12 14:13:47 +00:00
buildID := func ( name , exposed string ) string {
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( fmt . Sprintf ( ` FROM scratch
2017-01-10 18:16:25 +00:00
EXPOSE % s ` , exposed ) ) )
2016-01-28 14:19:25 +00:00
id := inspectField ( c , name , "Id" )
2014-11-12 14:13:47 +00:00
return id
}
id1 := buildID ( "testbuildexpose1" , "80 2375" )
id2 := buildID ( "testbuildexpose2" , "2375 80" )
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Errorf ( "EXPOSE should invalidate the cache only when ports actually changed" )
2014-11-12 14:13:47 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildExposeUpperCaseProto ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // Expose not implemented on Windows
2015-02-07 23:04:22 +00:00
name := "testbuildexposeuppercaseproto"
2015-03-26 19:43:00 +00:00
expected := "map[5678/udp:{}]"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM scratch
2017-01-10 18:16:25 +00:00
EXPOSE 5678 / UDP ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.ExposedPorts" )
2015-02-07 23:04:22 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Exposed ports %s, expected %s" , res , expected )
2015-02-07 23:04:22 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEmptyEntrypointInheritance ( c * check . C ) {
2014-10-24 00:23:25 +00:00
name := "testbuildentrypointinheritance"
name2 := "testbuildentrypointinheritance2"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ "/bin/echo" ] ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Entrypoint" )
2014-10-24 00:23:25 +00:00
2016-02-29 11:28:37 +00:00
expected := "[/bin/echo]"
2014-10-24 00:23:25 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-10-24 00:23:25 +00:00
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name2 , build . WithDockerfile ( fmt . Sprintf ( ` FROM % s
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ ] ` , name ) ) )
2016-01-28 14:19:25 +00:00
res = inspectField ( c , name2 , "Config.Entrypoint" )
2014-10-24 00:23:25 +00:00
2016-02-29 11:28:37 +00:00
expected = "[]"
2014-10-24 00:23:25 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-10-24 00:23:25 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEmptyEntrypoint ( c * check . C ) {
2014-05-31 12:43:32 +00:00
name := "testbuildentrypoint"
2016-02-29 11:28:37 +00:00
expected := "[]"
2014-09-03 19:17:17 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ ] ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Entrypoint" )
2014-05-31 12:43:32 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-05-31 12:43:32 +00:00
}
2014-09-01 20:33:06 +00:00
2014-09-03 19:17:17 +00:00
}
2014-09-01 20:33:06 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEntrypoint ( c * check . C ) {
2014-09-03 19:17:17 +00:00
name := "testbuildentrypoint"
2016-01-28 20:40:52 +00:00
2016-02-29 11:28:37 +00:00
expected := "[/bin/echo]"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ "/bin/echo" ] ` ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Entrypoint" )
2014-09-01 20:33:06 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-09-01 20:33:06 +00:00
}
2014-05-27 04:36:00 +00:00
}
2014-06-17 06:04:25 +00:00
// #6445 ensure ONBUILD triggers aren't committed to grandchildren
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildOnBuildLimitedInheritence ( c * check . C ) {
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "testonbuildtrigger1" , build . WithDockerfile ( `
2014-06-17 06:04:25 +00:00
FROM busybox
RUN echo "GRANDPARENT"
ONBUILD RUN echo "ONBUILD PARENT"
2017-01-10 18:16:25 +00:00
` ) )
2014-06-17 06:04:25 +00:00
// ONBUILD should be run in second build.
2017-03-23 17:35:22 +00:00
buildImage ( "testonbuildtrigger2" , build . WithDockerfile ( "FROM testonbuildtrigger1" ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
Out : "ONBUILD PARENT" ,
} )
2014-06-17 06:04:25 +00:00
// ONBUILD should *not* be run in third build.
2017-03-23 17:35:22 +00:00
result := buildImage ( "testonbuildtrigger3" , build . WithDockerfile ( "FROM testonbuildtrigger2" ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Success )
if strings . Contains ( result . Combined ( ) , "ONBUILD PARENT" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "ONBUILD instruction ran in grandchild of ONBUILD parent" )
2014-06-17 06:04:25 +00:00
}
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildSameDockerfileWithAndWithoutCache ( c * check . C ) {
2016-01-28 20:40:52 +00:00
testRequires ( c , DaemonIsLinux ) // Expose not implemented on Windows
2014-05-31 20:49:50 +00:00
name := "testbuildwithcache"
2017-01-10 18:16:25 +00:00
dockerfile := ` FROM scratch
2014-05-31 20:49:50 +00:00
MAINTAINER dockerio
EXPOSE 5432
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ "/bin/echo" ] `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 10:30:14 +00:00
id1 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 10:30:14 +00:00
id2 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , build . WithDockerfile ( dockerfile ) )
2017-01-16 10:30:14 +00:00
id3 := getIDByName ( c , name )
2014-05-31 20:49:50 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-05-31 20:49:50 +00:00
}
2017-01-10 18:16:25 +00:00
if id1 == id3 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-05-31 20:49:50 +00:00
}
}
2017-01-10 18:16:25 +00:00
// Make sure that ADD/COPY still populate the cache even if they don't use it
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildConditionalCache ( c * check . C ) {
2015-01-08 14:56:30 +00:00
name := "testbuildconditionalcache"
dockerfile := `
FROM busybox
ADD foo / tmp / `
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , map [ string ] string {
2015-01-08 14:56:30 +00:00
"foo" : "hello" ,
} )
2015-02-25 08:53:43 +00:00
defer ctx . Close ( )
2015-01-08 14:56:30 +00:00
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2015-01-08 14:56:30 +00:00
if err := ctx . Add ( "foo" , "bye" ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Error modifying foo: %s" , err )
2015-01-08 14:56:30 +00:00
}
2017-01-10 18:16:25 +00:00
// Updating a file should invalidate the cache
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name )
2015-01-08 14:56:30 +00:00
if id2 == id1 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Should not have used the cache" )
2015-01-08 14:56:30 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id3 := getIDByName ( c , name )
2015-01-08 14:56:30 +00:00
if id3 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Should have used the cache" )
2015-01-08 14:56:30 +00:00
}
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) this really seems to test the same thing as before
func ( s * DockerSuite ) TestBuildAddMultipleLocalFileWithAndWithoutCache ( c * check . C ) {
name := "testbuildaddmultiplelocalfilewithcache"
2014-05-31 20:49:50 +00:00
dockerfile := `
FROM busybox
MAINTAINER dockerio
2017-01-10 18:16:25 +00:00
ADD foo Dockerfile / usr / lib / bla /
RUN sh - c "[ $(cat /usr/lib/bla/foo) = " hello " ]" `
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , map [ string ] string {
2014-05-31 20:49:50 +00:00
"foo" : "hello" ,
} )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
id3 := getIDByName ( c , name )
2014-05-31 20:49:50 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-05-31 20:49:50 +00:00
}
2017-01-10 18:16:25 +00:00
if id1 == id3 {
c . Fatal ( "The cache should have been invalided but hasn't." )
}
2014-05-31 20:49:50 +00:00
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildCopyDirButNotFile ( c * check . C ) {
name := "testbuildcopydirbutnotfile"
name2 := "testbuildcopydirbutnotfile2"
2014-09-16 16:58:20 +00:00
dockerfile := `
2017-01-10 18:16:25 +00:00
FROM ` + minimalBaseImage() + `
COPY dir / tmp / `
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , map [ string ] string {
2017-01-10 18:16:25 +00:00
"dir/foo" : "hello" ,
2014-09-16 16:58:20 +00:00
} )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2017-01-10 18:16:25 +00:00
// Check that adding file with similar name doesn't mess with cache
if err := ctx . Add ( "dir_file" , "hello2" ) ; err != nil {
c . Fatal ( err )
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name2 , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name2 )
2014-09-16 16:58:20 +00:00
if id1 != id2 {
2017-01-10 18:16:25 +00:00
c . Fatal ( "The cache should have been used but wasn't" )
2014-09-16 16:58:20 +00:00
}
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildAddCurrentDirWithCache ( c * check . C ) {
name := "testbuildaddcurrentdirwithcache"
name2 := name + "2"
name3 := name + "3"
name4 := name + "4"
2014-05-31 20:49:50 +00:00
dockerfile := `
2017-01-10 18:16:25 +00:00
FROM ` + minimalBaseImage() + `
2014-05-31 20:49:50 +00:00
MAINTAINER dockerio
2017-01-10 18:16:25 +00:00
ADD . / usr / lib / bla `
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , map [ string ] string {
2014-05-31 20:49:50 +00:00
"foo" : "hello" ,
} )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2017-01-10 18:16:25 +00:00
// Check that adding file invalidate cache of "ADD ."
if err := ctx . Add ( "bar" , "hello2" ) ; err != nil {
c . Fatal ( err )
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name2 , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name2 )
2014-05-31 20:49:50 +00:00
if id1 == id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-05-31 20:49:50 +00:00
}
// Check that changing file invalidate cache of "ADD ."
if err := ctx . Add ( "foo" , "hello1" ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-05-31 20:49:50 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name3 , withExternalBuildContext ( ctx ) )
id3 := getIDByName ( c , name3 )
2014-05-31 20:49:50 +00:00
if id2 == id3 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-05-31 20:49:50 +00:00
}
2015-04-02 17:42:40 +00:00
// Check that changing file to same content with different mtime does not
// invalidate cache of "ADD ."
2014-05-31 20:49:50 +00:00
time . Sleep ( 1 * time . Second ) // wait second because of mtime precision
if err := ctx . Add ( "foo" , "hello1" ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-05-31 20:49:50 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name4 , withExternalBuildContext ( ctx ) )
id4 := getIDByName ( c , name4 )
2015-04-02 17:42:40 +00:00
if id3 != id4 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-05-31 20:49:50 +00:00
}
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) this really seems to test the same thing as before (TestBuildAddMultipleLocalFileWithAndWithoutCache)
2015-05-25 06:51:10 +00:00
func ( s * DockerSuite ) TestBuildAddCurrentDirWithoutCache ( c * check . C ) {
2014-05-31 20:49:50 +00:00
name := "testbuildaddcurrentdirwithoutcache"
dockerfile := `
2016-02-06 01:46:06 +00:00
FROM ` + minimalBaseImage() + `
2014-05-31 20:49:50 +00:00
MAINTAINER dockerio
ADD . / usr / lib / bla `
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , map [ string ] string {
2014-05-31 20:49:50 +00:00
"foo" : "hello" ,
} )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
id2 := getIDByName ( c , name )
2014-05-31 20:49:50 +00:00
if id1 == id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-05-31 20:49:50 +00:00
}
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildAddRemoteFileWithAndWithoutCache ( c * check . C ) {
2014-05-31 20:49:50 +00:00
name := "testbuildaddremotefilewithcache"
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , map [ string ] string {
2014-05-31 20:49:50 +00:00
"baz" : "hello" ,
} )
defer server . Close ( )
2015-02-19 10:01:27 +00:00
2017-01-10 18:16:25 +00:00
dockerfile := fmt . Sprintf ( ` FROM ` + minimalBaseImage ( ) + `
2014-05-31 20:49:50 +00:00
MAINTAINER dockerio
2017-01-10 18:16:25 +00:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 10:30:14 +00:00
id1 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerfile ) )
2017-01-16 10:30:14 +00:00
id2 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , build . WithDockerfile ( dockerfile ) )
2017-01-16 10:30:14 +00:00
id3 := getIDByName ( c , name )
2017-01-10 18:16:25 +00:00
2014-05-31 20:49:50 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-05-31 20:49:50 +00:00
}
2017-01-10 18:16:25 +00:00
if id1 == id3 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-05-31 20:49:50 +00:00
}
}
2015-05-25 06:51:10 +00:00
func ( s * DockerSuite ) TestBuildAddRemoteFileMTime ( c * check . C ) {
2014-10-22 18:16:42 +00:00
name := "testbuildaddremotefilemtime"
2014-11-17 16:05:49 +00:00
name2 := name + "2"
name3 := name + "3"
2015-02-19 10:01:27 +00:00
files := map [ string ] string { "baz" : "hello" }
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , files )
2014-10-22 18:16:42 +00:00
defer server . Close ( )
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , fmt . Sprintf ( ` FROM ` + minimalBaseImage ( ) + `
2014-10-22 18:16:42 +00:00
MAINTAINER dockerio
2015-02-19 10:01:27 +00:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) , nil )
2014-10-22 18:16:42 +00:00
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
buildImageSuccessfully ( c , name2 , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name2 )
2014-10-22 18:16:42 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been used but wasn't - #1" )
2014-10-22 18:16:42 +00:00
}
2015-04-02 17:42:40 +00:00
// Now create a different server with same contents (causes different mtime)
// The cache should still be used
2015-02-19 10:01:27 +00:00
// allow some time for clock to pass as mtime precision is only 1s
time . Sleep ( 2 * time . Second )
2017-01-16 10:30:14 +00:00
server2 := fakeStorage ( c , files )
2015-02-19 10:01:27 +00:00
defer server2 . Close ( )
2014-10-22 18:16:42 +00:00
2017-01-16 10:30:14 +00:00
ctx2 := fakeContext ( c , fmt . Sprintf ( ` FROM ` + minimalBaseImage ( ) + `
2015-02-19 10:01:27 +00:00
MAINTAINER dockerio
ADD % s / baz / usr / lib / baz / quux ` , server2 . URL ( ) ) , nil )
defer ctx2 . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name3 , withExternalBuildContext ( ctx2 ) )
id3 := getIDByName ( c , name3 )
2015-04-02 17:42:40 +00:00
if id1 != id3 {
c . Fatal ( "The cache should have been used but wasn't" )
2014-10-22 18:16:42 +00:00
}
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) this really seems to test the same thing as before (combined)
func ( s * DockerSuite ) TestBuildAddLocalAndRemoteFilesWithAndWithoutCache ( c * check . C ) {
2014-05-31 20:49:50 +00:00
name := "testbuildaddlocalandremotefilewithcache"
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , map [ string ] string {
2014-05-31 20:49:50 +00:00
"baz" : "hello" ,
} )
defer server . Close ( )
2015-02-19 10:01:27 +00:00
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , fmt . Sprintf ( ` FROM ` + minimalBaseImage ( ) + `
2014-05-31 20:49:50 +00:00
MAINTAINER dockerio
ADD foo / usr / lib / bla / bar
2015-02-19 10:01:27 +00:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) ,
2014-05-31 20:49:50 +00:00
map [ string ] string {
"foo" : "hello world" ,
} )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
id3 := getIDByName ( c , name )
2014-05-31 20:49:50 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-05-31 20:49:50 +00:00
}
2017-01-10 18:16:25 +00:00
if id1 == id3 {
c . Fatal ( "The cache should have been invalidated but hasn't." )
}
2014-05-31 20:49:50 +00:00
}
2015-04-18 16:46:47 +00:00
func testContextTar ( c * check . C , compression archive . Compression ) {
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c ,
2014-09-24 12:55:52 +00:00
` FROM busybox
ADD foo / foo
CMD [ "cat" , "/foo" ] ` ,
map [ string ] string {
"foo" : "bar" ,
} ,
)
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2014-09-24 12:55:52 +00:00
context , err := archive . Tar ( ctx . Dir , compression )
2014-05-09 22:26:41 +00:00
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to build context tar: %v" , err )
2014-05-09 22:26:41 +00:00
}
2014-09-24 12:55:52 +00:00
name := "contexttar"
2014-05-09 22:26:41 +00:00
2017-01-10 18:16:25 +00:00
icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "build" , "-t" , name , "-" } ,
Stdin : context ,
} ) . Assert ( c , icmd . Success )
2014-05-09 22:26:41 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildContextTarGzip ( c * check . C ) {
testContextTar ( c , archive . Gzip )
2014-05-09 22:26:41 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildContextTarNoCompression ( c * check . C ) {
testContextTar ( c , archive . Uncompressed )
2014-05-09 22:26:41 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildNoContext ( c * check . C ) {
2017-01-10 18:16:25 +00:00
name := "nocontext"
icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "build" , "-t" , name , "-" } ,
Stdin : strings . NewReader (
` FROM busybox
CMD [ "echo" , "ok" ] ` ) ,
} ) . Assert ( c , icmd . Success )
2014-05-09 22:26:41 +00:00
2015-04-18 16:46:47 +00:00
if out , _ := dockerCmd ( c , "run" , "--rm" , "nocontext" ) ; out != "ok\n" {
c . Fatalf ( "run produced invalid output: %q, expected %q" , out , "ok" )
2014-05-09 22:26:41 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildWithVolumeOwnership ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-06-02 21:46:28 +00:00
name := "testbuildimg"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox : latest
2014-06-02 21:46:28 +00:00
RUN mkdir / test && chown daemon : daemon / test && chmod 0600 / test
2017-01-10 18:16:25 +00:00
VOLUME / test ` ) )
2014-06-02 21:46:28 +00:00
2015-07-14 06:35:36 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , "testbuildimg" , "ls" , "-la" , "/test" )
2014-06-02 21:46:28 +00:00
if expected := "drw-------" ; ! strings . Contains ( out , expected ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected %s received %s" , expected , out )
2014-06-02 21:46:28 +00:00
}
if expected := "daemon daemon" ; ! strings . Contains ( out , expected ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected %s received %s" , expected , out )
2014-06-02 21:46:28 +00:00
}
}
2014-06-17 06:08:14 +00:00
// testing #1405 - config.Cmd does not get cleaned up if
// utilizing cache
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEntrypointRunCleanup ( c * check . C ) {
2014-06-17 06:08:14 +00:00
name := "testbuildcmdcleanup"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
RUN echo "hello" ` ) )
2014-06-17 06:08:14 +00:00
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
2014-06-17 06:08:14 +00:00
RUN echo "hello"
ADD foo / foo
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ "/bin/echo" ] ` ) ,
withFile ( "foo" , "hello" ) ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Cmd" )
2014-07-08 17:37:20 +00:00
// Cmd must be cleaned up
2016-02-29 11:28:37 +00:00
if res != "[]" {
2015-03-26 19:43:00 +00:00
c . Fatalf ( "Cmd %s, expected nil" , res )
2014-06-17 06:08:14 +00:00
}
}
2014-06-17 06:26:42 +00:00
2015-05-25 06:51:10 +00:00
func ( s * DockerSuite ) TestBuildAddFileNotFound ( c * check . C ) {
2014-06-17 06:35:29 +00:00
name := "testbuildaddnotfound"
2016-02-06 01:46:06 +00:00
expected := "foo: no such file or directory"
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-06 01:46:06 +00:00
expected = "foo: The system cannot find the file specified"
}
2017-01-16 10:30:14 +00:00
buildImage ( name , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "Dockerfile" , ` FROM ` + minimalBaseImage ( ) + `
ADD foo / usr / local / bar ` ) ,
withFile ( "bar" , "hello" ) ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : expected ,
} )
2014-06-17 06:35:29 +00:00
}
2014-06-17 06:50:51 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildInheritance ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-06-17 06:50:51 +00:00
name := "testbuildinheritance"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM scratch
2017-01-10 18:16:25 +00:00
EXPOSE 2375 ` ) )
2016-01-28 14:19:25 +00:00
ports1 := inspectField ( c , name , "Config.ExposedPorts" )
2014-06-17 06:50:51 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( fmt . Sprintf ( ` FROM % s
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ "/bin/echo" ] ` , name ) ) )
2014-06-17 06:50:51 +00:00
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Entrypoint" )
2016-02-29 11:28:37 +00:00
if expected := "[/bin/echo]" ; res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-06-17 06:50:51 +00:00
}
2016-01-28 14:19:25 +00:00
ports2 := inspectField ( c , name , "Config.ExposedPorts" )
2014-06-17 06:50:51 +00:00
if ports1 != ports2 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Ports must be same: %s != %s" , ports1 , ports2 )
2014-06-17 06:50:51 +00:00
}
}
2014-06-17 06:57:32 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildFails ( c * check . C ) {
2014-06-17 06:57:32 +00:00
name := "testbuildfails"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
RUN sh - c "exit 23" ` ) ) . Assert ( c , icmd . Expected {
ExitCode : 23 ,
Err : "returned a non-zero code: 23" ,
} )
2014-06-17 06:57:32 +00:00
}
2014-06-17 07:04:07 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildOnBuild ( c * check . C ) {
2014-06-17 07:14:45 +00:00
name := "testbuildonbuild"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
ONBUILD RUN touch foobar ` ) )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( fmt . Sprintf ( ` FROM % s
2017-01-10 18:16:25 +00:00
RUN [ - f foobar ] ` , name ) ) )
2014-06-17 07:14:45 +00:00
}
2014-06-17 07:24:47 +00:00
2014-06-17 07:49:07 +00:00
// gh #2446
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddToSymlinkDest ( c * check . C ) {
2016-09-08 01:20:51 +00:00
makeLink := ` ln -s /foo /bar `
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-09-08 01:20:51 +00:00
makeLink = ` mklink /D C:\bar C:\foo `
}
2014-06-17 07:49:07 +00:00
name := "testbuildaddtosymlinkdest"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
FROM busybox
RUN sh - c "mkdir /foo"
RUN ` +makeLink+ `
ADD foo / bar /
RUN sh - c "[ -f /bar/foo ]"
RUN sh - c "[ -f /foo/foo ]" ` ) ,
withFile ( "foo" , "hello" ) ,
) )
2014-06-17 07:49:07 +00:00
}
2014-06-25 06:54:53 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEscapeWhitespace ( c * check . C ) {
2016-04-22 22:04:46 +00:00
name := "testbuildescapewhitespace"
2014-06-25 06:54:53 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2016-04-22 22:04:46 +00:00
# ESCAPE = \
2014-06-25 06:54:53 +00:00
FROM busybox
MAINTAINER " Docker \
IO < io @ \
docker . com > "
2017-01-10 18:16:25 +00:00
` ) )
2014-06-25 06:54:53 +00:00
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Author" )
2014-12-11 12:56:21 +00:00
if res != "\"Docker IO <io@docker.com>\"" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Parsed string did not match the escaped string. Got: %q" , res )
2014-06-25 06:54:53 +00:00
}
}
2014-02-15 18:38:48 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildVerifyIntString ( c * check . C ) {
2014-12-11 12:56:21 +00:00
// Verify that strings that look like ints are still passed as strings
name := "testbuildstringing"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2017-01-10 18:16:25 +00:00
FROM busybox
MAINTAINER 123 ` ) )
2014-12-11 12:56:21 +00:00
2015-07-14 06:35:36 +00:00
out , _ := dockerCmd ( c , "inspect" , name )
2014-12-11 12:56:21 +00:00
if ! strings . Contains ( out , "\"123\"" ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Output does not contain the int as a string:\n%s" , out )
2014-12-11 12:56:21 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerignore ( c * check . C ) {
2014-02-15 18:38:48 +00:00
name := "testbuilddockerignore"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
FROM busybox
ADD . / bla
2016-02-06 01:46:06 +00:00
RUN sh - c "[[ -f /bla/src/x.go ]]"
RUN sh - c "[[ -f /bla/Makefile ]]"
RUN sh - c "[[ ! -e /bla/src/_vendor ]]"
RUN sh - c "[[ ! -e /bla/.gitignore ]]"
RUN sh - c "[[ ! -e /bla/README.md ]]"
RUN sh - c "[[ ! -e /bla/dir/foo ]]"
RUN sh - c "[[ ! -e /bla/foo ]]"
RUN sh - c "[[ ! -e /bla/.git ]]"
RUN sh - c "[[ ! -e v.cc ]]"
RUN sh - c "[[ ! -e src/v.cc ]]"
2017-01-10 18:16:25 +00:00
RUN sh - c "[[ ! -e src/_vendor/v.cc ]]" ` ) ,
withFile ( "Makefile" , "all:" ) ,
withFile ( ".git/HEAD" , "ref: foo" ) ,
withFile ( "src/x.go" , "package main" ) ,
withFile ( "src/_vendor/v.go" , "package main" ) ,
withFile ( "src/_vendor/v.cc" , "package main" ) ,
withFile ( "src/v.cc" , "package main" ) ,
withFile ( "v.cc" , "package main" ) ,
withFile ( "dir/foo" , "" ) ,
withFile ( ".gitignore" , "" ) ,
withFile ( "README.md" , "readme" ) ,
withFile ( ".dockerignore" , `
2015-04-09 19:07:06 +00:00
. git
pkg
. gitignore
src / _vendor
* . md
2015-10-14 21:42:21 +00:00
* * / * . cc
2017-01-10 18:16:25 +00:00
dir ` ) ,
) )
2014-02-15 18:38:48 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerignoreCleanPaths ( c * check . C ) {
2014-10-23 21:54:35 +00:00
name := "testbuilddockerignorecleanpaths"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
2014-10-23 21:54:35 +00:00
FROM busybox
ADD . / tmp /
2017-01-10 18:16:25 +00:00
RUN sh - c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)" ` ) ,
withFile ( "foo" , "foo" ) ,
withFile ( "foo2" , "foo2" ) ,
withFile ( "dir1/foo" , "foo in dir1" ) ,
withFile ( ".dockerignore" , "./foo\ndir1//foo\n./dir1/../foo2" ) ,
) )
2014-10-23 21:54:35 +00:00
}
2015-04-09 19:07:06 +00:00
func ( s * DockerSuite ) TestBuildDockerignoreExceptions ( c * check . C ) {
name := "testbuilddockerignoreexceptions"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
FROM busybox
ADD . / bla
2016-02-06 01:46:06 +00:00
RUN sh - c "[[ -f /bla/src/x.go ]]"
RUN sh - c "[[ -f /bla/Makefile ]]"
RUN sh - c "[[ ! -e /bla/src/_vendor ]]"
RUN sh - c "[[ ! -e /bla/.gitignore ]]"
RUN sh - c "[[ ! -e /bla/README.md ]]"
RUN sh - c "[[ -e /bla/dir/dir/foo ]]"
RUN sh - c "[[ ! -e /bla/dir/foo1 ]]"
RUN sh - c "[[ -f /bla/dir/e ]]"
RUN sh - c "[[ -f /bla/dir/e-dir/foo ]]"
RUN sh - c "[[ ! -e /bla/foo ]]"
RUN sh - c "[[ ! -e /bla/.git ]]"
2017-01-10 18:16:25 +00:00
RUN sh - c "[[ -e /bla/dir/a.cc ]]" ` ) ,
withFile ( "Makefile" , "all:" ) ,
withFile ( ".git/HEAD" , "ref: foo" ) ,
withFile ( "src/x.go" , "package main" ) ,
withFile ( "src/_vendor/v.go" , "package main" ) ,
withFile ( "dir/foo" , "" ) ,
withFile ( "dir/foo1" , "" ) ,
withFile ( "dir/dir/f1" , "" ) ,
withFile ( "dir/dir/foo" , "" ) ,
withFile ( "dir/e" , "" ) ,
withFile ( "dir/e-dir/foo" , "" ) ,
withFile ( ".gitignore" , "" ) ,
withFile ( "README.md" , "readme" ) ,
withFile ( "dir/a.cc" , "hello" ) ,
withFile ( ".dockerignore" , `
2015-04-09 19:07:06 +00:00
. git
pkg
. gitignore
src / _vendor
* . md
dir
! dir / e *
2015-10-14 21:42:21 +00:00
! dir / dir / foo
* * / * . cc
2017-01-10 18:16:25 +00:00
! * * / * . cc ` ) ,
) )
2015-04-09 19:07:06 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerignoringDockerfile ( c * check . C ) {
2014-02-15 18:38:48 +00:00
name := "testbuilddockerignoredockerfile"
dockerfile := `
2017-01-10 18:16:25 +00:00
FROM busybox
2014-10-23 21:30:11 +00:00
ADD . / tmp /
2016-02-06 01:46:06 +00:00
RUN sh - c "! ls /tmp/Dockerfile"
2014-10-23 21:30:11 +00:00
RUN ls / tmp / . dockerignore `
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , "Dockerfile\n" ) ,
) )
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , "./Dockerfile\n" ) ,
) )
2014-02-15 18:38:48 +00:00
}
2014-07-06 11:36:34 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerignoringRenamedDockerfile ( c * check . C ) {
2014-09-11 14:42:17 +00:00
name := "testbuilddockerignoredockerfile"
dockerfile := `
2017-01-10 18:16:25 +00:00
FROM busybox
2014-09-11 14:42:17 +00:00
ADD . / tmp /
RUN ls / tmp / Dockerfile
2016-02-06 01:46:06 +00:00
RUN sh - c "! ls /tmp/MyDockerfile"
2014-09-11 14:42:17 +00:00
RUN ls / tmp / . dockerignore `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "-f" , "MyDockerfile" ) , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "Dockerfile" , "Should not use me" ) ,
withFile ( "MyDockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , "MyDockerfile\n" ) ,
) )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "-f" , "MyDockerfile" ) , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "Dockerfile" , "Should not use me" ) ,
withFile ( "MyDockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , "./MyDockerfile\n" ) ,
) )
2014-09-11 14:42:17 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerignoringDockerignore ( c * check . C ) {
2014-10-23 21:30:11 +00:00
name := "testbuilddockerignoredockerignore"
dockerfile := `
2017-01-10 18:16:25 +00:00
FROM busybox
2014-10-23 21:30:11 +00:00
ADD . / tmp /
2016-02-06 01:46:06 +00:00
RUN sh - c "! ls /tmp/.dockerignore"
2014-10-23 21:30:11 +00:00
RUN ls / tmp / Dockerfile `
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , ".dockerignore\n" ) ,
) )
2014-10-23 21:30:11 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerignoreTouchDockerfile ( c * check . C ) {
2014-10-23 21:30:11 +00:00
name := "testbuilddockerignoretouchdockerfile"
dockerfile := `
FROM busybox
ADD . / tmp / `
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , map [ string ] string {
2014-10-23 21:30:11 +00:00
"Dockerfile" : dockerfile ,
".dockerignore" : "Dockerfile\n" ,
} )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2014-10-23 21:30:11 +00:00
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , name )
2014-10-23 21:30:11 +00:00
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 := getIDByName ( c , name )
2014-10-23 21:30:11 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Didn't use the cache - 1" )
2014-10-23 21:30:11 +00:00
}
// Now make sure touching Dockerfile doesn't invalidate the cache
2017-01-16 10:30:14 +00:00
if err := ctx . Add ( "Dockerfile" , dockerfile + "\n# hi" ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Didn't add Dockerfile: %s" , err )
2014-10-23 21:30:11 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 = getIDByName ( c , name )
2014-10-23 21:30:11 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Didn't use the cache - 2" )
2014-10-23 21:30:11 +00:00
}
// One more time but just 'touch' it instead of changing the content
2017-01-16 10:30:14 +00:00
if err := ctx . Add ( "Dockerfile" , dockerfile + "\n# hi" ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Didn't add Dockerfile: %s" , err )
2014-10-23 21:30:11 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
id2 = getIDByName ( c , name )
2014-10-23 21:30:11 +00:00
if id1 != id2 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Didn't use the cache - 3" )
2014-10-23 21:30:11 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerignoringWholeDir ( c * check . C ) {
2014-07-18 05:35:54 +00:00
name := "testbuilddockerignorewholedir"
2017-01-10 18:16:25 +00:00
2014-07-18 05:35:54 +00:00
dockerfile := `
2017-01-10 18:16:25 +00:00
FROM busybox
2014-07-18 05:35:54 +00:00
COPY . /
2016-02-06 01:46:06 +00:00
RUN sh - c "[[ ! -e /.gitignore ]]"
2017-01-10 18:16:25 +00:00
RUN sh - c "[[ ! -e /Makefile ]]" `
2015-05-30 02:38:56 +00:00
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , "*\n" ) ,
withFile ( "Makefile" , "all:" ) ,
withFile ( ".gitignore" , "" ) ,
) )
}
2015-05-30 02:38:56 +00:00
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildDockerignoringOnlyDotfiles ( c * check . C ) {
name := "testbuilddockerignorewholedir"
2015-05-30 02:38:56 +00:00
2017-01-10 18:16:25 +00:00
dockerfile := `
FROM busybox
COPY . /
RUN sh - c "[[ ! -e /.gitignore ]]"
RUN sh - c "[[ -f /Makefile ]]" `
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , ".*" ) ,
withFile ( "Makefile" , "all:" ) ,
withFile ( ".gitignore" , "" ) ,
) )
2014-07-18 05:35:54 +00:00
}
2015-05-30 02:38:56 +00:00
func ( s * DockerSuite ) TestBuildDockerignoringBadExclusion ( c * check . C ) {
2015-10-14 21:42:21 +00:00
name := "testbuilddockerignorebadexclusion"
2017-01-16 10:30:14 +00:00
buildImage ( name , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "Dockerfile" , `
FROM busybox
2015-05-30 02:38:56 +00:00
COPY . /
2016-02-06 01:46:06 +00:00
RUN sh - c "[[ ! -e /.gitignore ]]"
2017-01-10 18:16:25 +00:00
RUN sh - c "[[ -f /Makefile ]]" ` ) ,
withFile ( "Makefile" , "all:" ) ,
withFile ( ".gitignore" , "" ) ,
withFile ( ".dockerignore" , "!\n" ) ,
) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
2017-03-08 22:23:25 +00:00
Err : "Error checking context: 'illegal exclusion pattern: \"!\"" ,
2015-05-30 02:38:56 +00:00
} )
}
2015-10-14 21:42:21 +00:00
func ( s * DockerSuite ) TestBuildDockerignoringWildTopDir ( c * check . C ) {
dockerfile := `
2017-01-10 18:16:25 +00:00
FROM busybox
2015-10-14 21:42:21 +00:00
COPY . /
2016-02-06 01:46:06 +00:00
RUN sh - c "[[ ! -e /.dockerignore ]]"
RUN sh - c "[[ ! -e /Dockerfile ]]"
RUN sh - c "[[ ! -e /file1 ]]"
RUN sh - c "[[ ! -e /dir ]]" `
2015-10-14 21:42:21 +00:00
// All of these should result in ignoring all files
for _ , variant := range [ ] string { "**" , "**/" , "**/**" , "*" } {
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "noname" , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( "file1" , "" ) ,
withFile ( "dir/file1" , "" ) ,
withFile ( ".dockerignore" , variant ) ,
) )
dockerCmd ( c , "rmi" , "noname" )
2015-10-14 21:42:21 +00:00
}
}
func ( s * DockerSuite ) TestBuildDockerignoringWildDirs ( c * check . C ) {
dockerfile := `
FROM busybox
COPY . /
2016-02-06 01:46:06 +00:00
# RUN sh - c "[[ -e /.dockerignore ]]"
2016-03-03 23:16:10 +00:00
RUN sh - c " [ [ - e / Dockerfile ] ] && \
[ [ ! - e / file0 ] ] && \
[ [ ! - e / dir1 / file0 ] ] && \
[ [ ! - e / dir2 / file0 ] ] && \
[ [ ! - e / file1 ] ] && \
[ [ ! - e / dir1 / file1 ] ] && \
[ [ ! - e / dir1 / dir2 / file1 ] ] && \
[ [ ! - e / dir1 / file2 ] ] && \
[ [ - e / dir1 / dir2 / file2 ] ] && \
[ [ ! - e / dir1 / dir2 / file4 ] ] && \
[ [ ! - e / dir1 / dir2 / file5 ] ] && \
[ [ ! - e / dir1 / dir2 / file6 ] ] && \
[ [ ! - e / dir1 / dir3 / file7 ] ] && \
[ [ ! - e / dir1 / dir3 / file8 ] ] && \
[ [ - e / dir1 / dir3 ] ] && \
[ [ - e / dir1 / dir4 ] ] && \
[ [ ! - e ' dir1 / dir5 / fileAA ' ] ] && \
[ [ - e ' dir1 / dir5 / fileAB ' ] ] && \
[ [ - e ' dir1 / dir5 / fileB ' ] ] " # " . " in pattern means nothing
2015-10-14 21:42:21 +00:00
RUN echo all done ! `
2017-01-10 18:16:25 +00:00
dockerignore := `
2015-10-14 21:42:21 +00:00
* * / file0
* * / * file1
* * / dir1 / file2
dir1 /**/ file4
* * / dir2 / file5
* * / dir1 / dir2 / file6
dir1 / dir3 / * *
* * / dir4 / * *
* * / file ? A
* * / file \ ? B
* * / dir5 / file .
2017-01-10 18:16:25 +00:00
`
2015-10-14 21:42:21 +00:00
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "noname" , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , dockerignore ) ,
withFile ( "dir1/file0" , "" ) ,
withFile ( "dir1/dir2/file0" , "" ) ,
withFile ( "file1" , "" ) ,
withFile ( "dir1/file1" , "" ) ,
withFile ( "dir1/dir2/file1" , "" ) ,
withFile ( "dir1/file2" , "" ) ,
withFile ( "dir1/dir2/file2" , "" ) , // remains
withFile ( "dir1/dir2/file4" , "" ) ,
withFile ( "dir1/dir2/file5" , "" ) ,
withFile ( "dir1/dir2/file6" , "" ) ,
withFile ( "dir1/dir3/file7" , "" ) ,
withFile ( "dir1/dir3/file8" , "" ) ,
withFile ( "dir1/dir4/file9" , "" ) ,
withFile ( "dir1/dir5/fileAA" , "" ) ,
withFile ( "dir1/dir5/fileAB" , "" ) ,
withFile ( "dir1/dir5/fileB" , "" ) ,
) )
2015-10-14 21:42:21 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildLineBreak ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-06 11:36:34 +00:00
name := "testbuildlinebreak"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-07-06 11:36:34 +00:00
RUN sh - c ' echo root : testpass \
> / tmp / passwd '
RUN mkdir - p / var / run / sshd
2016-02-06 01:46:06 +00:00
RUN sh - c "[ " $ ( cat / tmp / passwd ) " = " root : testpass " ]"
2017-01-10 18:16:25 +00:00
RUN sh - c "[ " $ ( ls - d / var / run / sshd ) " = " / var / run / sshd " ]" ` ) )
2014-07-06 11:36:34 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEOLInLine ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-06 11:36:34 +00:00
name := "testbuildeolinline"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-07-06 11:36:34 +00:00
RUN sh - c ' echo root : testpass > / tmp / passwd '
RUN echo "foo \n bar" ; echo "baz"
RUN mkdir - p / var / run / sshd
2016-02-06 01:46:06 +00:00
RUN sh - c "[ " $ ( cat / tmp / passwd ) " = " root : testpass " ]"
2017-01-10 18:16:25 +00:00
RUN sh - c "[ " $ ( ls - d / var / run / sshd ) " = " / var / run / sshd " ]" ` ) )
2014-07-06 11:36:34 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCommentsShebangs ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-06 11:36:34 +00:00
name := "testbuildcomments"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-07-06 11:36:34 +00:00
# This is an ordinary comment .
RUN { echo ' # ! / bin / sh ' ; echo ' echo hello world ' ; } > / hello . sh
RUN [ ! - x / hello . sh ]
# comment with line break \
RUN chmod + x / hello . sh
RUN [ - x / hello . sh ]
RUN [ "$(cat /hello.sh)" = $ ' # ! / bin / sh \ necho hello world ' ]
2017-01-10 18:16:25 +00:00
RUN [ "$(/hello.sh)" = "hello world" ] ` ) )
2014-07-06 11:36:34 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildUsersAndGroups ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-06 11:36:34 +00:00
name := "testbuildusers"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2014-07-06 11:36:34 +00:00
# Make sure our defaults work
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = ' 0 : 0 / root : root ' ]
# TODO decide if "args.user = strconv.Itoa(syscall.Getuid())" is acceptable behavior for changeUser in sysvinit instead of "return nil" when "USER" isn ' t specified ( so that we get the proper group list even if that is the empty list , even in the default case of not supplying an explicit USER to run as , which implies USER 0 )
USER root
RUN [ "$(id -G):$(id -Gn)" = ' 0 10 : root wheel ' ]
# Setup dockerio user and group
2016-03-09 12:30:56 +00:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd && \
echo ' dockerio : x : 1001 : ' >> / etc / group
2014-07-06 11:36:34 +00:00
# Make sure we can switch to our user and all the information is exactly as we expect it to be
USER dockerio
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
# Switch back to root and double check that worked exactly as we might expect it to
USER root
2016-03-09 12:30:56 +00:00
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 0 : 0 / root : root / 0 10 : root wheel ' ] && \
2016-12-02 13:15:55 +00:00
# Add a "supplementary" group for our dockerio user
2016-03-09 12:30:56 +00:00
echo ' supplementary : x : 1002 : dockerio ' >> / etc / group
2014-07-06 11:36:34 +00:00
# ... and then go verify that we get it like we expect
USER dockerio
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 1002 : dockerio supplementary ' ]
USER 1001
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 1002 : dockerio supplementary ' ]
# super test the new "user:group" syntax
USER dockerio : dockerio
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER 1001 : dockerio
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER dockerio : 1001
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER 1001 : 1001
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER dockerio : supplementary
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
USER dockerio : 1002
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
USER 1001 : supplementary
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
USER 1001 : 1002
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
# make sure unknown uid / gid still works properly
USER 1042 : 1043
2017-01-10 18:16:25 +00:00
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1042 : 1043 / 1042 : 1043 / 1043 : 1043 ' ] ` ) )
2014-07-06 11:36:34 +00:00
}
2017-02-10 02:13:20 +00:00
// FIXME(vdemeester) rename this test (and probably "merge" it with the one below TestBuildEnvUsage2)
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvUsage ( c * check . C ) {
2015-09-18 17:41:12 +00:00
// /docker/world/hello is not owned by the correct user
testRequires ( c , NotUserNamespace )
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-06 11:36:34 +00:00
name := "testbuildenvusage"
dockerfile := ` FROM busybox
2014-10-25 18:29:18 +00:00
ENV HOME / root
2014-08-13 10:07:41 +00:00
ENV PATH $ HOME / bin : $ PATH
ENV PATH / tmp : $ PATH
RUN [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
2014-07-06 11:36:34 +00:00
ENV FOO / foo / baz
ENV BAR / bar
ENV BAZ $ BAR
ENV FOOPATH $ PATH : $ FOO
RUN [ "$BAR" = "$BAZ" ]
RUN [ "$FOOPATH" = "$PATH:/foo/baz" ]
2017-01-10 18:16:25 +00:00
ENV FROM hello / docker / world
2014-07-06 11:36:34 +00:00
ENV TO / docker / world / hello
ADD $ FROM $ TO
2014-08-13 10:07:41 +00:00
RUN [ "$(cat $TO)" = "hello" ]
2015-02-20 00:27:20 +00:00
ENV abc = def
ENV ghi = $ abc
RUN [ "$ghi" = "def" ]
2014-08-13 10:07:41 +00:00
`
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( "hello/docker/world" , "hello" ) ,
) )
2014-07-06 11:36:34 +00:00
}
2017-02-10 02:13:20 +00:00
// FIXME(vdemeester) rename this test (and probably "merge" it with the one above TestBuildEnvUsage)
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEnvUsage2 ( c * check . C ) {
2015-09-18 17:41:12 +00:00
// /docker/world/hello is not owned by the correct user
testRequires ( c , NotUserNamespace )
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-09-26 02:28:24 +00:00
name := "testbuildenvusage2"
dockerfile := ` FROM busybox
2016-01-23 00:09:51 +00:00
ENV abc = def def = "hello world"
RUN [ "$abc,$def" = "def,hello world" ]
ENV def = hello \ world v1 = abc v2 = "hi there" v3 = ' boogie nights ' v4 = "with'quotes too"
RUN [ "$def,$v1,$v2,$v3,$v4" = "hello world,abc,hi there,boogie nights,with'quotes too" ]
2014-09-26 02:28:24 +00:00
ENV abc = zzz FROM = hello / docker / world
ENV abc = zzz TO = / docker / world / hello
ADD $ FROM $ TO
2016-01-23 00:09:51 +00:00
RUN [ "$abc,$(cat $TO)" = "zzz,hello" ]
2014-09-26 02:28:24 +00:00
ENV abc ' yyy '
2015-01-29 02:28:48 +00:00
RUN [ $ abc = ' yyy ' ]
2014-09-26 02:28:24 +00:00
ENV abc =
RUN [ "$abc" = "" ]
2015-02-20 00:27:20 +00:00
# use grep to make sure if the builder substitutes \ $ foo by mistake
# we don ' t get a false positive
ENV abc = \ $ foo
RUN [ "$abc" = "\$foo" ] && ( echo "$abc" | grep foo )
ENV abc \ $ foo
RUN [ "$abc" = "\$foo" ] && ( echo "$abc" | grep foo )
2016-01-23 00:09:51 +00:00
ENV abc = \ ' foo \ ' abc2 = \ "foo\"
RUN [ "$abc,$abc2" = "'foo',\"foo\"" ]
2015-02-20 00:27:20 +00:00
ENV abc "foo"
2015-01-29 02:28:48 +00:00
RUN [ "$abc" = "foo" ]
2015-02-20 00:27:20 +00:00
ENV abc ' foo '
2015-01-29 02:28:48 +00:00
RUN [ "$abc" = ' foo ' ]
2015-02-20 00:27:20 +00:00
ENV abc \ ' foo \ '
2015-01-29 02:28:48 +00:00
RUN [ "$abc" = "'foo'" ]
2015-02-20 00:27:20 +00:00
ENV abc \ "foo\"
2015-01-29 02:28:48 +00:00
RUN [ "$abc" = ' "foo" ' ]
2015-01-29 02:28:48 +00:00
ENV abc = ABC
RUN [ "$abc" = "ABC" ]
2016-01-23 00:09:51 +00:00
ENV def1 = $ { abc : - DEF } def2 = $ { ccc : - DEF }
ENV def3 = $ { ccc : - $ { def2 } xx } def4 = $ { abc : + ALT } def5 = $ { def2 : + $ { abc } : } def6 = $ { ccc : - \ $ abc : } def7 = $ { ccc : - \ $ { abc } : }
RUN [ "$def1,$def2,$def3,$def4,$def5,$def6,$def7" = ' ABC , DEF , DEFxx , ALT , ABC : , $ abc : , $ { abc : } ' ]
2015-01-29 02:28:48 +00:00
ENV mypath = $ { mypath : + $ mypath : } / home
ENV mypath = $ { mypath : + $ mypath : } / away
RUN [ "$mypath" = ' / home : / away ' ]
2015-01-29 02:28:48 +00:00
ENV e1 = bar
2016-01-23 00:09:51 +00:00
ENV e2 = $ e1 e3 = $ e11 e4 = \ $ e1 e5 = \ $ e11
2015-01-29 02:28:48 +00:00
RUN [ "$e0,$e1,$e2,$e3,$e4,$e5" = ' , bar , bar , , $ e1 , $ e11 ' ]
ENV ee1 bar
ENV ee2 $ ee1
ENV ee3 $ ee11
ENV ee4 \ $ ee1
ENV ee5 \ $ ee11
RUN [ "$ee1,$ee2,$ee3,$ee4,$ee5" = ' bar , bar , , $ ee1 , $ ee11 ' ]
2016-01-23 00:09:51 +00:00
ENV eee1 = "foo" eee2 = ' foo '
2015-01-29 02:28:48 +00:00
ENV eee3 "foo"
ENV eee4 ' foo '
RUN [ "$eee1,$eee2,$eee3,$eee4" = ' foo , foo , foo , foo ' ]
2014-09-26 02:28:24 +00:00
`
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( "hello/docker/world" , "hello" ) ,
) )
2014-09-26 02:28:24 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddScript ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-07-06 11:36:34 +00:00
name := "testbuildaddscript"
dockerfile := `
FROM busybox
ADD test / test
RUN [ "chmod" , "+x" , "/test" ]
RUN [ "/test" ]
RUN [ "$(cat /testfile)" = ' test ! ' ] `
2014-11-20 17:38:41 +00:00
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( "test" , "#!/bin/sh\necho 'test!' > /testfile" ) ,
) )
2014-07-06 11:36:34 +00:00
}
2014-07-08 19:34:04 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddTar ( c * check . C ) {
2015-09-18 17:41:12 +00:00
// /test/foo is not owned by the correct user
testRequires ( c , NotUserNamespace )
2014-07-09 09:39:38 +00:00
name := "testbuildaddtar"
2014-07-08 19:34:04 +00:00
2014-07-21 19:10:47 +00:00
ctx := func ( ) * FakeContext {
2014-07-21 22:02:31 +00:00
dockerfile := `
FROM busybox
ADD test . tar /
RUN cat / test / foo | grep Hi
ADD test . tar / test . tar
RUN cat / test . tar / test / foo | grep Hi
ADD test . tar / unlikely - to - exist
RUN cat / unlikely - to - exist / test / foo | grep Hi
ADD test . tar / unlikely - to - exist - trailing - slash /
RUN cat / unlikely - to - exist - trailing - slash / test / foo | grep Hi
2016-02-09 02:12:04 +00:00
RUN sh - c "mkdir /existing-directory" # sh - c is needed on Windows to use the correct mkdir
2014-07-21 22:02:31 +00:00
ADD test . tar / existing - directory
RUN cat / existing - directory / test / foo | grep Hi
ADD test . tar / existing - directory - trailing - slash /
RUN cat / existing - directory - trailing - slash / test / foo | grep Hi `
2014-07-21 19:10:47 +00:00
tmpDir , err := ioutil . TempDir ( "" , "fake-context" )
2015-09-20 22:00:55 +00:00
c . Assert ( err , check . IsNil )
2014-07-21 19:10:47 +00:00
testTar , err := os . Create ( filepath . Join ( tmpDir , "test.tar" ) )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to create test.tar archive: %v" , err )
2014-07-08 19:34:04 +00:00
}
2014-07-21 19:10:47 +00:00
defer testTar . Close ( )
tw := tar . NewWriter ( testTar )
if err := tw . WriteHeader ( & tar . Header {
Name : "test/foo" ,
Size : 2 ,
} ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to write tar file header: %v" , err )
2014-07-21 19:10:47 +00:00
}
if _ , err := tw . Write ( [ ] byte ( "Hi" ) ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to write tar file content: %v" , err )
2014-07-21 19:10:47 +00:00
}
if err := tw . Close ( ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to close tar archive: %v" , err )
2014-07-08 19:34:04 +00:00
}
2014-07-21 22:02:31 +00:00
if err := ioutil . WriteFile ( filepath . Join ( tmpDir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to open destination dockerfile: %v" , err )
2014-07-21 19:10:47 +00:00
}
2015-03-10 03:53:28 +00:00
return fakeContextFromDir ( tmpDir )
2014-07-21 19:10:47 +00:00
} ( )
2014-11-20 17:38:41 +00:00
defer ctx . Close ( )
2014-07-21 19:10:47 +00:00
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2014-07-08 19:34:04 +00:00
}
2014-07-24 07:19:16 +00:00
2015-11-20 16:49:33 +00:00
func ( s * DockerSuite ) TestBuildAddBrokenTar ( c * check . C ) {
name := "testbuildaddbrokentar"
ctx := func ( ) * FakeContext {
dockerfile := `
FROM busybox
ADD test . tar / `
tmpDir , err := ioutil . TempDir ( "" , "fake-context" )
c . Assert ( err , check . IsNil )
testTar , err := os . Create ( filepath . Join ( tmpDir , "test.tar" ) )
if err != nil {
c . Fatalf ( "failed to create test.tar archive: %v" , err )
}
defer testTar . Close ( )
tw := tar . NewWriter ( testTar )
if err := tw . WriteHeader ( & tar . Header {
Name : "test/foo" ,
Size : 2 ,
} ) ; err != nil {
c . Fatalf ( "failed to write tar file header: %v" , err )
}
if _ , err := tw . Write ( [ ] byte ( "Hi" ) ) ; err != nil {
c . Fatalf ( "failed to write tar file content: %v" , err )
}
if err := tw . Close ( ) ; err != nil {
c . Fatalf ( "failed to close tar archive: %v" , err )
}
// Corrupt the tar by removing one byte off the end
stat , err := testTar . Stat ( )
if err != nil {
c . Fatalf ( "failed to stat tar archive: %v" , err )
}
if err := testTar . Truncate ( stat . Size ( ) - 1 ) ; err != nil {
c . Fatalf ( "failed to truncate tar archive: %v" , err )
}
if err := ioutil . WriteFile ( filepath . Join ( tmpDir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 ) ; err != nil {
c . Fatalf ( "failed to open destination dockerfile: %v" , err )
}
return fakeContextFromDir ( tmpDir )
} ( )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImage ( name , withExternalBuildContext ( ctx ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2015-11-20 16:49:33 +00:00
}
func ( s * DockerSuite ) TestBuildAddNonTar ( c * check . C ) {
name := "testbuildaddnontar"
// Should not try to extract test.tar
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
2015-11-20 16:49:33 +00:00
FROM busybox
ADD test . tar /
2017-01-10 18:16:25 +00:00
RUN test - f / test . tar ` ) ,
withFile ( "test.tar" , "not_a_tar_file" ) ,
) )
2015-11-20 16:49:33 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddTarXz ( c * check . C ) {
2015-09-18 17:41:12 +00:00
// /test/foo is not owned by the correct user
testRequires ( c , NotUserNamespace )
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-12-08 20:40:27 +00:00
name := "testbuildaddtarxz"
ctx := func ( ) * FakeContext {
dockerfile := `
FROM busybox
ADD test . tar . xz /
RUN cat / test / foo | grep Hi `
tmpDir , err := ioutil . TempDir ( "" , "fake-context" )
2015-09-20 22:00:55 +00:00
c . Assert ( err , check . IsNil )
2014-12-08 20:40:27 +00:00
testTar , err := os . Create ( filepath . Join ( tmpDir , "test.tar" ) )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to create test.tar archive: %v" , err )
2014-12-08 20:40:27 +00:00
}
defer testTar . Close ( )
tw := tar . NewWriter ( testTar )
if err := tw . WriteHeader ( & tar . Header {
Name : "test/foo" ,
Size : 2 ,
} ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to write tar file header: %v" , err )
2014-12-08 20:40:27 +00:00
}
if _ , err := tw . Write ( [ ] byte ( "Hi" ) ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to write tar file content: %v" , err )
2014-12-08 20:40:27 +00:00
}
if err := tw . Close ( ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to close tar archive: %v" , err )
2014-12-08 20:40:27 +00:00
}
2015-07-14 06:35:36 +00:00
2017-01-16 15:39:12 +00:00
icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { "xz" , "-k" , "test.tar" } ,
Dir : tmpDir ,
} ) . Assert ( c , icmd . Success )
2014-12-08 20:40:27 +00:00
if err := ioutil . WriteFile ( filepath . Join ( tmpDir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to open destination dockerfile: %v" , err )
2014-12-08 20:40:27 +00:00
}
2015-03-10 03:53:28 +00:00
return fakeContextFromDir ( tmpDir )
2014-12-08 20:40:27 +00:00
} ( )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2014-12-08 20:40:27 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildAddTarXzGz ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-12-08 20:40:27 +00:00
name := "testbuildaddtarxzgz"
ctx := func ( ) * FakeContext {
dockerfile := `
FROM busybox
ADD test . tar . xz . gz /
RUN ls / test . tar . xz . gz `
tmpDir , err := ioutil . TempDir ( "" , "fake-context" )
2015-09-20 22:00:55 +00:00
c . Assert ( err , check . IsNil )
2014-12-08 20:40:27 +00:00
testTar , err := os . Create ( filepath . Join ( tmpDir , "test.tar" ) )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to create test.tar archive: %v" , err )
2014-12-08 20:40:27 +00:00
}
defer testTar . Close ( )
tw := tar . NewWriter ( testTar )
if err := tw . WriteHeader ( & tar . Header {
Name : "test/foo" ,
Size : 2 ,
} ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to write tar file header: %v" , err )
2014-12-08 20:40:27 +00:00
}
if _ , err := tw . Write ( [ ] byte ( "Hi" ) ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to write tar file content: %v" , err )
2014-12-08 20:40:27 +00:00
}
if err := tw . Close ( ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to close tar archive: %v" , err )
2014-12-08 20:40:27 +00:00
}
2017-01-16 15:39:12 +00:00
icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { "xz" , "-k" , "test.tar" } ,
Dir : tmpDir ,
} ) . Assert ( c , icmd . Success )
2014-12-08 20:40:27 +00:00
2017-01-16 15:39:12 +00:00
icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { "gzip" , "test.tar.xz" } ,
Dir : tmpDir ,
} )
2014-12-08 20:40:27 +00:00
if err := ioutil . WriteFile ( filepath . Join ( tmpDir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "failed to open destination dockerfile: %v" , err )
2014-12-08 20:40:27 +00:00
}
2015-03-10 03:53:28 +00:00
return fakeContextFromDir ( tmpDir )
2014-12-08 20:40:27 +00:00
} ( )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2014-12-08 20:40:27 +00:00
}
[nit] integration-cli: obey Go's naming convention
No substantial code change.
- Api --> API
- Cli --> CLI
- Http, Https --> HTTP, HTTPS
- Id --> ID
- Uid,Gid,Pid --> UID,PID,PID
- Ipam --> IPAM
- Tls --> TLS (TestDaemonNoTlsCliTlsVerifyWithEnv --> TestDaemonTLSVerifyIssue13964)
Didn't touch in this commit:
- Git: because it is officially "Git": https://git-scm.com/
- Tar: because it is officially "Tar": https://www.gnu.org/software/tar/
- Cpu, Nat, Mac, Ipc, Shm: for keeping a consistency with existing production code (not changable, for compatibility)
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
2016-09-28 01:50:12 +00:00
func ( s * DockerSuite ) TestBuildFromGit ( c * check . C ) {
2014-07-24 07:19:16 +00:00
name := "testbuildfromgit"
2017-01-16 10:30:14 +00:00
git := newFakeGit ( c , "repo" , map [ string ] string {
2014-07-24 07:19:16 +00:00
"Dockerfile" : ` FROM busybox
2017-01-10 18:16:25 +00:00
ADD first / first
RUN [ - f / first ]
MAINTAINER docker ` ,
2014-07-24 07:19:16 +00:00
"first" : "test git data" ,
2015-03-10 03:53:28 +00:00
} , true )
2014-07-24 07:19:16 +00:00
defer git . Close ( )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithContextPath ( git . RepoURL ) )
2017-01-10 18:16:25 +00:00
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Author" )
2014-07-24 07:19:16 +00:00
if res != "docker" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Maintainer should be docker, got %s" , res )
2014-07-24 07:19:16 +00:00
}
}
2014-07-08 17:37:20 +00:00
[nit] integration-cli: obey Go's naming convention
No substantial code change.
- Api --> API
- Cli --> CLI
- Http, Https --> HTTP, HTTPS
- Id --> ID
- Uid,Gid,Pid --> UID,PID,PID
- Ipam --> IPAM
- Tls --> TLS (TestDaemonNoTlsCliTlsVerifyWithEnv --> TestDaemonTLSVerifyIssue13964)
Didn't touch in this commit:
- Git: because it is officially "Git": https://git-scm.com/
- Tar: because it is officially "Tar": https://www.gnu.org/software/tar/
- Cpu, Nat, Mac, Ipc, Shm: for keeping a consistency with existing production code (not changable, for compatibility)
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
2016-09-28 01:50:12 +00:00
func ( s * DockerSuite ) TestBuildFromGitWithContext ( c * check . C ) {
2015-04-24 22:12:45 +00:00
name := "testbuildfromgit"
2017-01-16 10:30:14 +00:00
git := newFakeGit ( c , "repo" , map [ string ] string {
2015-04-24 22:12:45 +00:00
"docker/Dockerfile" : ` FROM busybox
ADD first / first
RUN [ - f / first ]
MAINTAINER docker ` ,
"docker/first" : "test git data" ,
} , true )
defer git . Close ( )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithContextPath ( fmt . Sprintf ( "%s#master:docker" , git . RepoURL ) ) )
2017-01-10 18:16:25 +00:00
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Author" )
2015-04-24 22:12:45 +00:00
if res != "docker" {
c . Fatalf ( "Maintainer should be docker, got %s" , res )
}
}
[nit] integration-cli: obey Go's naming convention
No substantial code change.
- Api --> API
- Cli --> CLI
- Http, Https --> HTTP, HTTPS
- Id --> ID
- Uid,Gid,Pid --> UID,PID,PID
- Ipam --> IPAM
- Tls --> TLS (TestDaemonNoTlsCliTlsVerifyWithEnv --> TestDaemonTLSVerifyIssue13964)
Didn't touch in this commit:
- Git: because it is officially "Git": https://git-scm.com/
- Tar: because it is officially "Tar": https://www.gnu.org/software/tar/
- Cpu, Nat, Mac, Ipc, Shm: for keeping a consistency with existing production code (not changable, for compatibility)
Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
2016-09-28 01:50:12 +00:00
func ( s * DockerSuite ) TestBuildFromGitwithF ( c * check . C ) {
2015-07-27 14:49:42 +00:00
name := "testbuildfromgitwithf"
2017-01-16 10:30:14 +00:00
git := newFakeGit ( c , "repo" , map [ string ] string {
2015-07-27 14:49:42 +00:00
"myApp/myDockerfile" : ` FROM busybox
RUN echo hi from Dockerfile ` ,
} , true )
defer git . Close ( )
2017-03-23 17:35:22 +00:00
buildImage ( name , cli . WithFlags ( "-f" , "myApp/myDockerfile" ) , build . WithContextPath ( git . RepoURL ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
Out : "hi from Dockerfile" ,
} )
2015-07-27 14:49:42 +00:00
}
2015-04-04 14:54:43 +00:00
func ( s * DockerSuite ) TestBuildFromRemoteTarball ( c * check . C ) {
name := "testbuildfromremotetarball"
buffer := new ( bytes . Buffer )
tw := tar . NewWriter ( buffer )
defer tw . Close ( )
dockerfile := [ ] byte ( ` FROM busybox
MAINTAINER docker ` )
if err := tw . WriteHeader ( & tar . Header {
Name : "Dockerfile" ,
Size : int64 ( len ( dockerfile ) ) ,
} ) ; err != nil {
c . Fatalf ( "failed to write tar file header: %v" , err )
}
if _ , err := tw . Write ( dockerfile ) ; err != nil {
c . Fatalf ( "failed to write tar file content: %v" , err )
}
if err := tw . Close ( ) ; err != nil {
c . Fatalf ( "failed to close tar archive: %v" , err )
}
2017-01-16 10:30:14 +00:00
server := fakeBinaryStorage ( c , map [ string ] * bytes . Buffer {
2015-04-04 14:54:43 +00:00
"testT.tar" : buffer ,
} )
defer server . Close ( )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithContextPath ( server . URL ( ) + "/testT.tar" ) )
2015-04-04 14:54:43 +00:00
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Author" )
2015-04-04 14:54:43 +00:00
if res != "docker" {
c . Fatalf ( "Maintainer should be docker, got %s" , res )
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCleanupCmdOnEntrypoint ( c * check . C ) {
2014-07-08 17:37:20 +00:00
name := "testbuildcmdcleanuponentrypoint"
2017-01-10 18:16:25 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
CMD [ "test" ]
ENTRYPOINT [ "echo" ] ` ) )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( fmt . Sprintf ( ` FROM % s
2017-01-10 18:16:25 +00:00
ENTRYPOINT [ "cat" ] ` , name ) ) )
2016-01-28 14:19:25 +00:00
res := inspectField ( c , name , "Config.Cmd" )
2016-02-29 11:28:37 +00:00
if res != "[]" {
2015-03-26 19:43:00 +00:00
c . Fatalf ( "Cmd %s, expected nil" , res )
2014-07-08 17:37:20 +00:00
}
2016-01-28 14:19:25 +00:00
res = inspectField ( c , name , "Config.Entrypoint" )
2016-02-29 11:28:37 +00:00
if expected := "[cat]" ; res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-07-08 17:37:20 +00:00
}
}
2014-08-30 11:34:09 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildClearCmd ( c * check . C ) {
2014-08-30 11:34:09 +00:00
name := "testbuildclearcmd"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2014-08-30 11:34:09 +00:00
ENTRYPOINT [ "/bin/bash" ]
2017-01-10 18:16:25 +00:00
CMD [ ] ` ) )
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "Config.Cmd" )
2014-08-30 11:34:09 +00:00
if res != "[]" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Cmd %s, expected %s" , res , "[]" )
2014-08-30 11:34:09 +00:00
}
}
2014-09-23 06:18:46 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEmptyCmd ( c * check . C ) {
2016-09-21 18:11:13 +00:00
// Skip on Windows. Base image on Windows has a CMD set in the image.
testRequires ( c , DaemonIsLinux )
2016-06-28 19:22:16 +00:00
2014-09-23 06:18:46 +00:00
name := "testbuildemptycmd"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM " + minimalBaseImage ( ) + "\nMAINTAINER quux\n" ) )
2017-01-10 18:16:25 +00:00
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "Config.Cmd" )
2014-09-23 06:18:46 +00:00
if res != "null" {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Cmd %s, expected %s" , res , "null" )
2014-09-23 06:18:46 +00:00
}
}
2014-09-23 20:31:42 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildOnBuildOutput ( c * check . C ) {
2014-09-23 20:31:42 +00:00
name := "testbuildonbuildparent"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nONBUILD RUN echo foo\n" ) )
2014-09-23 20:31:42 +00:00
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( "FROM " + name + "\nMAINTAINER quux\n" ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
Out : "# Executing 1 build trigger" ,
} )
2014-09-23 20:31:42 +00:00
}
2014-09-29 09:52:13 +00:00
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) should be a unit test
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildInvalidTag ( c * check . C ) {
2015-03-24 11:25:26 +00:00
name := "abcd:" + stringutils . GenerateRandomAlphaOnlyString ( 200 )
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( "FROM " + minimalBaseImage ( ) + "\nMAINTAINER quux\n" ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 125 ,
2017-01-11 21:54:52 +00:00
Err : "invalid reference format" ,
2017-01-10 18:16:25 +00:00
} )
2014-09-29 09:52:13 +00:00
}
2014-09-29 17:23:10 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCmdShDashC ( c * check . C ) {
2014-09-29 17:23:10 +00:00
name := "testbuildcmdshc"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nCMD echo cmd\n" ) )
2014-09-29 17:23:10 +00:00
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "Config.Cmd" )
2014-09-29 17:23:10 +00:00
expected := ` ["/bin/sh","-c","echo cmd"] `
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-09 02:12:04 +00:00
expected = ` ["cmd","/S","/C","echo cmd"] `
}
2014-09-29 17:23:10 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Expected value %s not in Config.Cmd: %s" , expected , res )
2014-09-29 17:23:10 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCmdSpaces ( c * check . C ) {
2015-01-15 19:34:59 +00:00
// Test to make sure that when we strcat arrays we take into account
// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
// look the same
name := "testbuildcmdspaces"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nCMD [\"echo hi\"]\n" ) )
2017-01-16 10:30:14 +00:00
id1 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nCMD [\"echo\", \"hi\"]\n" ) )
2017-01-16 10:30:14 +00:00
id2 := getIDByName ( c , name )
2015-01-15 19:34:59 +00:00
if id1 == id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Should not have resulted in the same CMD" )
2015-01-15 19:34:59 +00:00
}
// Now do the same with ENTRYPOINT
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nENTRYPOINT [\"echo hi\"]\n" ) )
2017-01-16 10:30:14 +00:00
id1 = getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n" ) )
2017-01-16 10:30:14 +00:00
id2 = getIDByName ( c , name )
2015-01-15 19:34:59 +00:00
if id1 == id2 {
2015-04-18 16:46:47 +00:00
c . Fatal ( "Should not have resulted in the same ENTRYPOINT" )
2015-01-15 19:34:59 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildCmdJSONNoShDashC ( c * check . C ) {
2014-09-29 17:23:10 +00:00
name := "testbuildcmdjson"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nCMD [\"echo\", \"cmd\"]" ) )
2014-09-29 17:23:10 +00:00
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "Config.Cmd" )
2014-09-29 17:23:10 +00:00
expected := ` ["echo","cmd"] `
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Expected value %s not in Config.Cmd: %s" , expected , res )
2014-09-29 17:23:10 +00:00
}
}
2014-10-07 03:14:25 +00:00
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildEntrypointCanBeOverridenByChild ( c * check . C ) {
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "parent" , build . WithDockerfile ( `
2014-10-07 22:39:50 +00:00
FROM busybox
ENTRYPOINT exit 130
2017-01-10 18:16:25 +00:00
` ) )
2014-10-07 22:39:50 +00:00
2017-01-10 18:16:25 +00:00
icmd . RunCommand ( dockerBinary , "run" , "parent" ) . Assert ( c , icmd . Expected {
ExitCode : 130 ,
} )
2014-10-07 22:39:50 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "child" , build . WithDockerfile ( `
2014-10-07 22:39:50 +00:00
FROM parent
ENTRYPOINT exit 5
2017-01-10 18:16:25 +00:00
` ) )
2014-10-07 22:39:50 +00:00
2017-01-10 18:16:25 +00:00
icmd . RunCommand ( dockerBinary , "run" , "child" ) . Assert ( c , icmd . Expected {
ExitCode : 5 ,
} )
2014-10-07 22:39:50 +00:00
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildEntrypointCanBeOverridenByChildInspect ( c * check . C ) {
2014-10-07 22:39:50 +00:00
var (
name = "testbuildepinherit"
name2 = "testbuildepinherit2"
expected = ` ["/bin/sh","-c","echo quux"] `
)
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-09 02:12:04 +00:00
expected = ` ["cmd","/S","/C","echo quux"] `
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nENTRYPOINT /foo/bar" ) )
buildImageSuccessfully ( c , name2 , build . WithDockerfile ( fmt . Sprintf ( "FROM %s\nENTRYPOINT echo quux" , name ) ) )
2014-10-07 22:39:50 +00:00
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name2 , "Config.Entrypoint" )
2014-10-07 22:39:50 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Expected value %s not in Config.Entrypoint: %s" , expected , res )
2014-10-07 22:39:50 +00:00
}
2017-01-10 18:16:25 +00:00
icmd . RunCommand ( dockerBinary , "run" , name2 ) . Assert ( c , icmd . Expected {
Out : "quux" ,
} )
2014-10-07 22:39:50 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildRunShEntrypoint ( c * check . C ) {
2014-10-07 22:39:50 +00:00
name := "testbuildentrypoint"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
ENTRYPOINT echo ` ) )
2015-07-14 06:35:36 +00:00
dockerCmd ( c , "run" , "--rm" , name )
2014-10-07 22:39:50 +00:00
}
2014-10-14 06:58:55 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildExoticShellInterpolation ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-10-14 06:58:55 +00:00
name := "testbuildexoticshellinterpolation"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2014-10-14 06:58:55 +00:00
FROM busybox
2014-12-16 15:06:45 +00:00
2014-10-14 06:58:55 +00:00
ENV SOME_VAR a . b . c
RUN [ "$SOME_VAR" = ' a . b . c ' ]
RUN [ "${SOME_VAR}" = ' a . b . c ' ]
RUN [ "${SOME_VAR%.*}" = ' a . b ' ]
RUN [ "${SOME_VAR%%.*}" = 'a' ]
RUN [ "${SOME_VAR#*.}" = ' b . c ' ]
RUN [ "${SOME_VAR##*.}" = 'c' ]
RUN [ "${SOME_VAR/c/d}" = ' a . b . d ' ]
RUN [ "${#SOME_VAR}" = '5' ]
RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = ' a . b . c ' ]
RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = ' Version : a . b . c ' ]
RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = ' ' ]
RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = ' a . b . c ' ]
2017-01-10 18:16:25 +00:00
` ) )
2014-10-14 06:58:55 +00:00
}
2014-10-09 03:34:20 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildVerifySingleQuoteFails ( c * check . C ) {
2014-10-09 03:34:20 +00:00
// This testcase is supposed to generate an error because the
// JSON array we're passing in on the CMD uses single quotes instead
// of double quotes (per the JSON spec). This means we interpret it
2015-12-13 16:00:39 +00:00
// as a "string" instead of "JSON array" and pass it on to "sh -c" and
2014-10-09 03:34:20 +00:00
// it should barf on it.
name := "testbuildsinglequotefails"
2017-01-10 18:16:25 +00:00
expectedExitCode := 2
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2017-01-10 18:16:25 +00:00
expectedExitCode = 127
2015-07-14 06:35:36 +00:00
}
2014-10-09 03:34:20 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
CMD [ ' / bin / sh ' , ' - c ' , ' echo hi ' ] ` ) )
2014-10-09 03:34:20 +00:00
2017-01-10 18:16:25 +00:00
icmd . RunCommand ( dockerBinary , "run" , "--rm" , name ) . Assert ( c , icmd . Expected {
ExitCode : expectedExitCode ,
} )
2014-10-09 03:34:20 +00:00
}
2014-10-06 16:41:22 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildVerboseOut ( c * check . C ) {
2014-10-06 16:41:22 +00:00
name := "testbuildverboseout"
2016-02-09 02:12:04 +00:00
expected := "\n123\n"
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-09 02:12:04 +00:00
expected = "\n123\r\n"
}
2014-10-06 16:41:22 +00:00
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
RUN echo 123 ` ) ) . Assert ( c , icmd . Expected {
Out : expected ,
} )
2014-10-06 16:41:22 +00:00
}
2014-10-08 21:55:02 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildWithTabs ( c * check . C ) {
2014-10-08 21:55:02 +00:00
name := "testbuildwithtabs"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( "FROM busybox\nRUN echo\tone\t\ttwo" ) )
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "ContainerConfig.Cmd" )
2015-01-20 19:11:59 +00:00
expected1 := ` ["/bin/sh","-c","echo\tone\t\ttwo"] `
expected2 := ` ["/bin/sh","-c","echo\u0009one\u0009\u0009two"] ` // syntactically equivalent, and what Go 1.3 generates
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-09 02:12:04 +00:00
expected1 = ` ["cmd","/S","/C","echo\tone\t\ttwo"] `
expected2 = ` ["cmd","/S","/C","echo\u0009one\u0009\u0009two"] ` // syntactically equivalent, and what Go 1.3 generates
}
2015-01-20 19:11:59 +00:00
if res != expected1 && res != expected2 {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Missing tabs.\nGot: %s\nExp: %s or %s" , res , expected1 , expected2 )
2014-10-08 21:55:02 +00:00
}
}
2014-12-04 22:06:40 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildLabels ( c * check . C ) {
2015-02-17 15:20:06 +00:00
name := "testbuildlabel"
expected := ` { "License":"GPL","Vendor":"Acme"} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2015-02-17 15:20:06 +00:00
LABEL Vendor = Acme
2017-01-10 18:16:25 +00:00
LABEL License GPL ` ) )
2016-01-28 14:19:25 +00:00
res := inspectFieldJSON ( c , name , "Config.Labels" )
2015-02-17 15:20:06 +00:00
if res != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Labels %s, expected %s" , res , expected )
2015-02-17 15:20:06 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildLabelsCache ( c * check . C ) {
2015-03-19 17:06:06 +00:00
name := "testbuildlabelcache"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
LABEL Vendor = Acme ` ) )
2017-01-16 10:30:14 +00:00
id1 := getIDByName ( c , name )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
LABEL Vendor = Acme ` ) )
2017-01-16 10:30:14 +00:00
id2 := getIDByName ( c , name )
2017-01-10 18:16:25 +00:00
if id1 != id2 {
2017-01-16 10:30:14 +00:00
c . Fatalf ( "Build 2 should have worked & used cache(%s,%s)" , id1 , id2 )
2015-03-19 17:06:06 +00:00
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
LABEL Vendor = Acme1 ` ) )
2017-01-16 10:30:14 +00:00
id2 = getIDByName ( c , name )
2017-01-10 18:16:25 +00:00
if id1 == id2 {
2017-01-16 10:30:14 +00:00
c . Fatalf ( "Build 3 should have worked & NOT used cache(%s,%s)" , id1 , id2 )
2015-03-19 17:06:06 +00:00
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
LABEL Vendor Acme ` ) )
2017-01-16 10:30:14 +00:00
id2 = getIDByName ( c , name )
2017-01-10 18:16:25 +00:00
if id1 != id2 {
2017-01-16 10:30:14 +00:00
c . Fatalf ( "Build 4 should have worked & used cache(%s,%s)" , id1 , id2 )
2015-03-20 12:14:31 +00:00
}
// Now make sure the cache isn't used by mistake
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
LABEL f1 = b1 f2 = b2 ` ) )
2015-03-20 12:14:31 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
LABEL f1 = b1 f2 = b2 ` ) )
2017-01-16 10:30:14 +00:00
id2 = getIDByName ( c , name )
2017-01-10 18:16:25 +00:00
if id1 == id2 {
2017-01-16 10:30:14 +00:00
c . Fatalf ( "Build 6 should have worked & NOT used the cache(%s,%s)" , id1 , id2 )
2015-03-19 17:06:06 +00:00
}
}
2015-10-28 00:29:21 +00:00
func ( s * DockerSuite ) TestBuildNotVerboseSuccess ( c * check . C ) {
// This test makes sure that -q works correctly when build is successful:
// stdout has only the image ID (long image ID) and stderr is empty.
outRegexp := regexp . MustCompile ( "^(sha256:|)[a-z0-9]{64}\\n$" )
2017-03-23 17:35:22 +00:00
buildFlags := cli . WithFlags ( "-q" )
2015-10-28 00:29:21 +00:00
tt := [ ] struct {
Name string
2017-01-10 18:16:25 +00:00
BuildFunc func ( string ) * icmd . Result
2015-10-28 00:29:21 +00:00
} {
{
Name : "quiet_build_stdin_success" ,
2017-01-10 18:16:25 +00:00
BuildFunc : func ( name string ) * icmd . Result {
2017-03-23 17:35:22 +00:00
return buildImage ( name , buildFlags , build . WithDockerfile ( "FROM busybox" ) )
2015-10-28 00:29:21 +00:00
} ,
} ,
{
Name : "quiet_build_ctx_success" ,
2017-01-10 18:16:25 +00:00
BuildFunc : func ( name string ) * icmd . Result {
2017-01-16 10:30:14 +00:00
return buildImage ( name , buildFlags , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "Dockerfile" , "FROM busybox" ) ,
withFile ( "quiet_build_success_fctx" , "test" ) ,
) )
2015-10-28 00:29:21 +00:00
} ,
} ,
{
Name : "quiet_build_git_success" ,
2017-01-10 18:16:25 +00:00
BuildFunc : func ( name string ) * icmd . Result {
2017-01-16 10:30:14 +00:00
git := newFakeGit ( c , "repo" , map [ string ] string {
2015-10-28 00:29:21 +00:00
"Dockerfile" : "FROM busybox" ,
} , true )
2017-03-23 17:35:22 +00:00
return buildImage ( name , buildFlags , build . WithContextPath ( git . RepoURL ) )
2015-10-28 00:29:21 +00:00
} ,
} ,
}
for _ , te := range tt {
2017-01-10 18:16:25 +00:00
result := te . BuildFunc ( te . Name )
result . Assert ( c , icmd . Success )
if outRegexp . Find ( [ ] byte ( result . Stdout ( ) ) ) == nil {
c . Fatalf ( "Test %s expected stdout to match the [%v] regexp, but it is [%v]" , te . Name , outRegexp , result . Stdout ( ) )
2015-10-28 00:29:21 +00:00
}
2016-07-06 21:34:14 +00:00
2017-01-10 18:16:25 +00:00
if result . Stderr ( ) != "" {
c . Fatalf ( "Test %s expected stderr to be empty, but it is [%#v]" , te . Name , result . Stderr ( ) )
2015-10-28 00:29:21 +00:00
}
}
}
2016-04-28 01:29:05 +00:00
func ( s * DockerSuite ) TestBuildNotVerboseFailureWithNonExistImage ( c * check . C ) {
// This test makes sure that -q works correctly when build fails by
// comparing between the stderr output in quiet mode and in stdout
// and stderr output in verbose mode
testRequires ( c , Network )
testName := "quiet_build_not_exists_image"
2017-01-10 18:16:25 +00:00
dockerfile := "FROM busybox11"
2017-03-23 17:35:22 +00:00
quietResult := buildImage ( testName , cli . WithFlags ( "-q" ) , build . WithDockerfile ( dockerfile ) )
2017-01-10 18:16:25 +00:00
quietResult . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2017-03-23 17:35:22 +00:00
result := buildImage ( testName , build . WithDockerfile ( dockerfile ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
if quietResult . Stderr ( ) != result . Combined ( ) {
c . Fatal ( fmt . Errorf ( "Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]" , testName , quietResult . Stderr ( ) , result . Combined ( ) ) )
2016-04-28 01:29:05 +00:00
}
}
2015-10-28 00:29:21 +00:00
func ( s * DockerSuite ) TestBuildNotVerboseFailure ( c * check . C ) {
// This test makes sure that -q works correctly when build fails by
// comparing between the stderr output in quiet mode and in stdout
// and stderr output in verbose mode
2017-01-10 18:16:25 +00:00
testCases := [ ] struct {
testName string
dockerfile string
2015-10-28 00:29:21 +00:00
} {
{ "quiet_build_no_from_at_the_beginning" , "RUN whoami" } ,
{ "quiet_build_unknown_instr" , "FROMD busybox" } ,
}
2017-01-10 18:16:25 +00:00
for _ , tc := range testCases {
2017-03-23 17:35:22 +00:00
quietResult := buildImage ( tc . testName , cli . WithFlags ( "-q" ) , build . WithDockerfile ( tc . dockerfile ) )
2017-01-10 18:16:25 +00:00
quietResult . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2017-03-23 17:35:22 +00:00
result := buildImage ( tc . testName , build . WithDockerfile ( tc . dockerfile ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
if quietResult . Stderr ( ) != result . Combined ( ) {
c . Fatal ( fmt . Errorf ( "Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]" , tc . testName , quietResult . Stderr ( ) , result . Combined ( ) ) )
2015-10-28 00:29:21 +00:00
}
}
}
func ( s * DockerSuite ) TestBuildNotVerboseFailureRemote ( c * check . C ) {
// This test ensures that when given a wrong URL, stderr in quiet mode and
2016-06-07 16:15:44 +00:00
// stderr in verbose mode are identical.
// TODO(vdemeester) with cobra, stdout has a carriage return too much so this test should not check stdout
URL := "http://something.invalid"
2017-01-10 18:16:25 +00:00
name := "quiet_build_wrong_remote"
2017-03-23 17:35:22 +00:00
quietResult := buildImage ( name , cli . WithFlags ( "-q" ) , build . WithContextPath ( URL ) )
2017-01-10 18:16:25 +00:00
quietResult . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithContextPath ( URL ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
if strings . TrimSpace ( quietResult . Stderr ( ) ) != strings . TrimSpace ( result . Combined ( ) ) {
c . Fatal ( fmt . Errorf ( "Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]" , name , quietResult . Stderr ( ) , result . Combined ( ) ) )
2015-10-28 00:29:21 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildStderr ( c * check . C ) {
2014-12-04 22:06:40 +00:00
// This test just makes sure that no non-error output goes
// to stderr
name := "testbuildstderr"
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithDockerfile ( "FROM busybox\nRUN echo one" ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Success )
2015-03-16 06:59:10 +00:00
2017-01-03 19:40:44 +00:00
// Windows to non-Windows should have a security warning
2017-01-13 16:23:28 +00:00
if runtime . GOOS == "windows" && testEnv . DaemonPlatform ( ) != "windows" && ! strings . Contains ( result . Stdout ( ) , "SECURITY WARNING:" ) {
2017-01-10 18:16:25 +00:00
c . Fatalf ( "Stdout contains unexpected output: %q" , result . Stdout ( ) )
2017-01-03 19:40:44 +00:00
}
// Stderr should always be empty
2017-01-10 18:16:25 +00:00
if result . Stderr ( ) != "" {
c . Fatalf ( "Stderr should have been empty, instead it's: %q" , result . Stderr ( ) )
2014-12-04 22:06:40 +00:00
}
}
2014-12-10 19:09:03 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildChownSingleFile ( c * check . C ) {
2017-01-10 18:16:25 +00:00
testRequires ( c , UnixCli , DaemonIsLinux ) // test uses chown: not available on windows
2015-02-20 09:37:27 +00:00
2014-12-10 19:09:03 +00:00
name := "testbuildchownsinglefile"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , `
2014-12-10 19:09:03 +00:00
FROM busybox
COPY test /
RUN ls - l / test
RUN [ $ ( ls - l / test | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
` , map [ string ] string {
"test" : "test" ,
} )
defer ctx . Close ( )
if err := os . Chown ( filepath . Join ( ctx . Dir , "test" ) , 4242 , 4242 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-10 19:09:03 +00:00
}
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2014-12-10 19:09:03 +00:00
}
2014-12-03 19:04:51 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildSymlinkBreakout ( c * check . C ) {
2014-12-03 19:04:51 +00:00
name := "testbuildsymlinkbreakout"
tmpdir , err := ioutil . TempDir ( "" , name )
2015-09-20 22:00:55 +00:00
c . Assert ( err , check . IsNil )
2014-12-03 19:04:51 +00:00
defer os . RemoveAll ( tmpdir )
ctx := filepath . Join ( tmpdir , "context" )
if err := os . MkdirAll ( ctx , 0755 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-03 19:04:51 +00:00
}
if err := ioutil . WriteFile ( filepath . Join ( ctx , "Dockerfile" ) , [ ] byte ( `
from busybox
add symlink . tar /
add inject / symlink /
` ) , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-03 19:04:51 +00:00
}
inject := filepath . Join ( ctx , "inject" )
if err := ioutil . WriteFile ( inject , nil , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-03 19:04:51 +00:00
}
f , err := os . Create ( filepath . Join ( ctx , "symlink.tar" ) )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2014-12-03 19:04:51 +00:00
}
w := tar . NewWriter ( f )
w . WriteHeader ( & tar . Header {
Name : "symlink2" ,
Typeflag : tar . TypeSymlink ,
Linkname : "/../../../../../../../../../../../../../../" ,
Uid : os . Getuid ( ) ,
Gid : os . Getgid ( ) ,
} )
w . WriteHeader ( & tar . Header {
Name : "symlink" ,
Typeflag : tar . TypeSymlink ,
Linkname : filepath . Join ( "symlink2" , tmpdir ) ,
Uid : os . Getuid ( ) ,
Gid : os . Getgid ( ) ,
} )
w . Close ( )
f . Close ( )
2017-01-16 10:30:14 +00:00
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithoutCache , withExternalBuildContext ( fakeContextFromDir ( ctx ) ) )
2014-12-03 19:04:51 +00:00
if _ , err := os . Lstat ( filepath . Join ( tmpdir , "inject" ) ) ; err == nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( "symlink breakout - inject" )
2014-12-03 19:04:51 +00:00
} else if ! os . IsNotExist ( err ) {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "unexpected error: %v" , err )
2014-12-03 19:04:51 +00:00
}
}
2014-12-08 22:33:46 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildXZHost ( c * check . C ) {
2015-09-18 17:41:12 +00:00
// /usr/local/sbin/xz gets permission denied for the user
testRequires ( c , NotUserNamespace )
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2014-12-08 22:33:46 +00:00
name := "testbuildxzhost"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
2014-12-08 22:33:46 +00:00
FROM busybox
ADD xz / usr / local / sbin /
RUN chmod 755 / usr / local / sbin / xz
ADD test . xz /
2017-01-10 18:16:25 +00:00
RUN [ ! - e / injected ] ` ) ,
2017-03-23 17:35:22 +00:00
withFile ( "test.xz" , "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" + "\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" + "\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21" ) ,
2017-01-10 18:16:25 +00:00
withFile ( "xz" , "#!/bin/sh\ntouch /injected" ) ,
) )
2014-12-08 22:33:46 +00:00
}
2014-12-12 19:15:31 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildVolumesRetainContents ( c * check . C ) {
2015-09-18 17:41:12 +00:00
// /foo/file gets permission denied for the user
testRequires ( c , NotUserNamespace )
2016-02-09 02:12:04 +00:00
testRequires ( c , DaemonIsLinux ) // TODO Windows: Issue #20127
2014-12-12 19:15:31 +00:00
var (
name = "testbuildvolumescontent"
expected = "some text"
2016-02-09 02:12:04 +00:00
volName = "/foo"
2014-12-12 19:15:31 +00:00
)
2016-02-09 02:12:04 +00:00
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-09 02:12:04 +00:00
volName = "C:/foo"
}
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
FROM busybox
COPY content / foo / file
VOLUME ` +volName+ `
CMD cat / foo / file ` ) ,
withFile ( "content" , expected ) ,
) )
2014-12-12 19:15:31 +00:00
2015-07-14 06:35:36 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , name )
2014-12-12 19:15:31 +00:00
if out != expected {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "expected file contents for /foo/file to be %q but received %q" , expected , out )
2014-12-12 19:15:31 +00:00
}
}
2014-09-11 14:42:17 +00:00
2017-02-10 02:13:20 +00:00
// FIXME(vdemeester) part of this should be unit test, other part should be clearer
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildRenamedDockerfile ( c * check . C ) {
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , ` FROM busybox
2014-09-11 14:42:17 +00:00
RUN echo from Dockerfile ` ,
map [ string ] string {
"Dockerfile" : "FROM busybox\nRUN echo from Dockerfile" ,
"files/Dockerfile" : "FROM busybox\nRUN echo from files/Dockerfile" ,
"files/dFile" : "FROM busybox\nRUN echo from files/dFile" ,
"dFile" : "FROM busybox\nRUN echo from dFile" ,
2015-02-04 14:07:37 +00:00
"files/dFile2" : "FROM busybox\nRUN echo from files/dFile2" ,
2014-09-11 14:42:17 +00:00
} )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "-t" , "test1" , "." ) , cli . InDir ( ctx . Dir ) ) . Assert ( c , icmd . Expected {
Out : "from Dockerfile" ,
} )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "-f" , filepath . Join ( "files" , "Dockerfile" ) , "-t" , "test2" , "." ) , cli . InDir ( ctx . Dir ) ) . Assert ( c , icmd . Expected {
Out : "from files/Dockerfile" ,
} )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , fmt . Sprintf ( "--file=%s" , filepath . Join ( "files" , "dFile" ) ) , "-t" , "test3" , "." ) , cli . InDir ( ctx . Dir ) ) . Assert ( c , icmd . Expected {
Out : "from files/dFile" ,
} )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "--file=dFile" , "-t" , "test4" , "." ) , cli . InDir ( ctx . Dir ) ) . Assert ( c , icmd . Expected {
Out : "from dFile" ,
} )
2014-09-11 14:42:17 +00:00
2015-09-01 14:00:40 +00:00
dirWithNoDockerfile , err := ioutil . TempDir ( os . TempDir ( ) , "test5" )
c . Assert ( err , check . IsNil )
2015-02-18 07:59:13 +00:00
nonDockerfileFile := filepath . Join ( dirWithNoDockerfile , "notDockerfile" )
if _ , err = os . Create ( nonDockerfileFile ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-18 07:59:13 +00:00
}
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , fmt . Sprintf ( "--file=%s" , nonDockerfileFile ) , "-t" , "test5" , "." ) , cli . InDir ( ctx . Dir ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : fmt . Sprintf ( "The Dockerfile (%s) must be within the build context (.)" , nonDockerfileFile ) ,
} )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "-f" , filepath . Join ( ".." , "Dockerfile" ) , "-t" , "test6" , ".." ) , cli . InDir ( filepath . Join ( ctx . Dir , "files" ) ) ) . Assert ( c , icmd . Expected {
Out : "from Dockerfile" ,
} )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "-f" , filepath . Join ( ctx . Dir , "files" , "Dockerfile" ) , "-t" , "test7" , ".." ) , cli . InDir ( filepath . Join ( ctx . Dir , "files" ) ) ) . Assert ( c , icmd . Expected {
Out : "from files/Dockerfile" ,
} )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "-f" , filepath . Join ( ".." , "Dockerfile" ) , "-t" , "test8" , "." ) , cli . InDir ( filepath . Join ( ctx . Dir , "files" ) ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "must be within the build context" ,
} )
2014-09-11 14:42:17 +00:00
2015-02-04 14:07:37 +00:00
tmpDir := os . TempDir ( )
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "-t" , "test9" , ctx . Dir ) , cli . InDir ( tmpDir ) ) . Assert ( c , icmd . Expected {
Out : "from Dockerfile" ,
} )
2014-09-11 14:42:17 +00:00
2017-03-27 15:12:48 +00:00
cli . Docker ( cli . Args ( "build" , "-f" , "dFile2" , "-t" , "test10" , "." ) , cli . InDir ( filepath . Join ( ctx . Dir , "files" ) ) ) . Assert ( c , icmd . Expected {
Out : "from files/dFile2" ,
} )
2014-09-11 14:42:17 +00:00
}
2014-10-07 01:54:52 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildFromMixedcaseDockerfile ( c * check . C ) {
testRequires ( c , UnixCli ) // Dockerfile overwrites dockerfile on windows
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-02-17 18:25:36 +00:00
2017-01-10 18:16:25 +00:00
// If Dockerfile is not present, use dockerfile
2017-01-16 10:30:14 +00:00
buildImage ( "test1" , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "dockerfile" , ` FROM busybox
RUN echo from dockerfile ` ) ,
) ) . Assert ( c , icmd . Expected {
Out : "from dockerfile" ,
} )
2015-02-17 18:25:36 +00:00
2017-01-10 18:16:25 +00:00
// Prefer Dockerfile in place of dockerfile
2017-01-16 10:30:14 +00:00
buildImage ( "test1" , withBuildContext ( c ,
2017-01-10 18:16:25 +00:00
withFile ( "dockerfile" , ` FROM busybox
RUN echo from dockerfile ` ) ,
withFile ( "Dockerfile" , ` FROM busybox
RUN echo from Dockerfile ` ) ,
) ) . Assert ( c , icmd . Expected {
Out : "from Dockerfile" ,
} )
2015-02-17 18:25:36 +00:00
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildFromURLWithF ( c * check . C ) {
2017-01-16 10:30:14 +00:00
server := fakeStorage ( c , map [ string ] string { "baz" : ` FROM busybox
2015-02-17 18:25:36 +00:00
RUN echo from baz
COPY * / tmp /
RUN find / tmp / ` } )
defer server . Close ( )
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , ` FROM busybox
2015-02-17 18:25:36 +00:00
RUN echo from Dockerfile ` ,
map [ string ] string { } )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2015-02-17 18:25:36 +00:00
// Make sure that -f is ignored and that we don't use the Dockerfile
// that's in the current dir
2017-03-23 17:35:22 +00:00
result := buildImage ( "test1" , cli . WithFlags ( "-f" , "baz" , server . URL ( ) + "/baz" ) , func ( cmd * icmd . Cmd ) func ( ) {
2017-01-10 18:16:25 +00:00
cmd . Dir = ctx . Dir
return nil
} )
result . Assert ( c , icmd . Success )
2015-02-17 18:25:36 +00:00
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "from baz" ) ||
strings . Contains ( result . Combined ( ) , "/tmp/baz" ) ||
! strings . Contains ( result . Combined ( ) , "/tmp/Dockerfile" ) {
c . Fatalf ( "Missing proper output: %s" , result . Combined ( ) )
2015-02-17 18:25:36 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildFromStdinWithF ( c * check . C ) {
2016-02-09 02:12:04 +00:00
testRequires ( c , DaemonIsLinux ) // TODO Windows: This test is flaky; no idea why
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , ` FROM busybox
2016-02-09 02:12:04 +00:00
RUN echo "from Dockerfile" ` ,
2015-02-17 18:25:36 +00:00
map [ string ] string { } )
2015-10-09 16:51:15 +00:00
defer ctx . Close ( )
2015-02-17 18:25:36 +00:00
// Make sure that -f is ignored and that we don't use the Dockerfile
// that's in the current dir
2017-03-23 17:35:22 +00:00
result := buildImage ( "test1" , cli . WithFlags ( "-f" , "baz" , "-" ) , func ( cmd * icmd . Cmd ) func ( ) {
2017-01-10 18:16:25 +00:00
cmd . Dir = ctx . Dir
cmd . Stdin = strings . NewReader ( ` FROM busybox
2016-02-09 02:12:04 +00:00
RUN echo "from baz"
2015-02-17 18:25:36 +00:00
COPY * / tmp /
2016-02-09 02:12:04 +00:00
RUN sh - c "find /tmp/" # sh - c is needed on Windows to use the correct find ` )
2017-01-10 18:16:25 +00:00
return nil
} )
result . Assert ( c , icmd . Success )
2015-02-17 18:25:36 +00:00
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "from baz" ) ||
strings . Contains ( result . Combined ( ) , "/tmp/baz" ) ||
! strings . Contains ( result . Combined ( ) , "/tmp/Dockerfile" ) {
c . Fatalf ( "Missing proper output: %s" , result . Combined ( ) )
2015-02-17 18:25:36 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildFromOfficialNames ( c * check . C ) {
2014-10-07 01:54:52 +00:00
name := "testbuildfromofficial"
fromNames := [ ] string {
"busybox" ,
"docker.io/busybox" ,
"index.docker.io/busybox" ,
"library/busybox" ,
"docker.io/library/busybox" ,
"index.docker.io/library/busybox" ,
}
for idx , fromName := range fromNames {
imgName := fmt . Sprintf ( "%s%d" , name , idx )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , imgName , build . WithDockerfile ( "FROM " + fromName ) )
2017-01-10 18:16:25 +00:00
dockerCmd ( c , "rmi" , imgName )
2014-10-07 01:54:52 +00:00
}
}
2015-02-02 21:17:12 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDockerfileOutsideContext ( c * check . C ) {
2017-01-10 18:16:25 +00:00
testRequires ( c , UnixCli , DaemonIsLinux ) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
2015-02-20 09:37:27 +00:00
2015-02-02 21:17:12 +00:00
name := "testbuilddockerfileoutsidecontext"
tmpdir , err := ioutil . TempDir ( "" , name )
2015-09-20 22:00:55 +00:00
c . Assert ( err , check . IsNil )
2015-02-02 21:17:12 +00:00
defer os . RemoveAll ( tmpdir )
ctx := filepath . Join ( tmpdir , "context" )
if err := os . MkdirAll ( ctx , 0755 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-02 21:17:12 +00:00
}
2015-02-04 14:07:37 +00:00
if err := ioutil . WriteFile ( filepath . Join ( ctx , "Dockerfile" ) , [ ] byte ( "FROM scratch\nENV X Y" ) , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-02 21:17:12 +00:00
}
wd , err := os . Getwd ( )
if err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-02 21:17:12 +00:00
}
defer os . Chdir ( wd )
if err := os . Chdir ( ctx ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-02 21:17:12 +00:00
}
2015-02-04 14:07:37 +00:00
if err := ioutil . WriteFile ( filepath . Join ( tmpdir , "outsideDockerfile" ) , [ ] byte ( "FROM scratch\nENV x y" ) , 0644 ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-02 21:17:12 +00:00
}
2015-02-17 00:59:41 +00:00
if err := os . Symlink ( filepath . Join ( ".." , "outsideDockerfile" ) , filepath . Join ( ctx , "dockerfile1" ) ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-02 21:17:12 +00:00
}
if err := os . Symlink ( filepath . Join ( tmpdir , "outsideDockerfile" ) , filepath . Join ( ctx , "dockerfile2" ) ) ; err != nil {
2015-04-18 16:46:47 +00:00
c . Fatal ( err )
2015-02-02 21:17:12 +00:00
}
2015-02-17 00:59:41 +00:00
2015-02-02 21:17:12 +00:00
for _ , dockerfilePath := range [ ] string {
2015-02-17 00:59:41 +00:00
filepath . Join ( ".." , "outsideDockerfile" ) ,
2015-02-02 21:17:12 +00:00
filepath . Join ( ctx , "dockerfile1" ) ,
filepath . Join ( ctx , "dockerfile2" ) ,
} {
2016-08-04 16:57:34 +00:00
result := dockerCmdWithResult ( "build" , "-t" , name , "--no-cache" , "-f" , dockerfilePath , "." )
2016-08-16 21:51:38 +00:00
c . Assert ( result , icmd . Matches , icmd . Expected {
2016-08-04 16:57:34 +00:00
Err : "must be within the build context" ,
ExitCode : 1 ,
} )
2015-02-02 21:17:12 +00:00
deleteImages ( name )
}
os . Chdir ( tmpdir )
// Path to Dockerfile should be resolved relative to working directory, not relative to context.
// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
2015-07-27 18:13:25 +00:00
out , _ , err := dockerCmdWithError ( "build" , "-t" , name , "--no-cache" , "-f" , "Dockerfile" , ctx )
2015-02-02 21:17:12 +00:00
if err == nil {
2015-04-18 16:46:47 +00:00
c . Fatalf ( "Expected error. Out: %s" , out )
2015-02-02 21:17:12 +00:00
}
}
2015-01-15 14:49:48 +00:00
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) should be a unit test
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildSpaces ( c * check . C ) {
2015-01-15 14:49:48 +00:00
// Test to make sure that leading/trailing spaces on a command
// doesn't change the error msg we get
name := "testspaces"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , "FROM busybox\nCOPY\n" ,
2015-01-15 14:49:48 +00:00
map [ string ] string {
2015-02-08 03:30:44 +00:00
"Dockerfile" : "FROM busybox\nCOPY\n" ,
2015-01-15 14:49:48 +00:00
} )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
result1 := buildImage ( name , withExternalBuildContext ( ctx ) )
result1 . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2015-01-15 14:49:48 +00:00
2015-02-08 03:30:44 +00:00
ctx . Add ( "Dockerfile" , "FROM busybox\nCOPY " )
2017-01-16 10:30:14 +00:00
result2 := buildImage ( name , withExternalBuildContext ( ctx ) )
result2 . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2015-01-15 14:49:48 +00:00
2015-03-21 19:43:14 +00:00
removeLogTimestamps := func ( s string ) string {
return regexp . MustCompile ( ` time="(.*?)" ` ) . ReplaceAllString ( s , ` time=[TIMESTAMP] ` )
}
2015-01-15 14:49:48 +00:00
// Skip over the times
2017-01-16 10:30:14 +00:00
e1 := removeLogTimestamps ( result1 . Error . Error ( ) )
e2 := removeLogTimestamps ( result2 . Error . Error ( ) )
2015-01-15 14:49:48 +00:00
// Ignore whitespace since that's what were verifying doesn't change stuff
if strings . Replace ( e1 , " " , "" , - 1 ) != strings . Replace ( e2 , " " , "" , - 1 ) {
2017-01-16 10:30:14 +00:00
c . Fatalf ( "Build 2's error wasn't the same as build 1's\n1:%s\n2:%s" , result1 . Error , result2 . Error )
2015-01-15 14:49:48 +00:00
}
2015-02-08 03:30:44 +00:00
ctx . Add ( "Dockerfile" , "FROM busybox\n COPY" )
2017-03-23 17:35:22 +00:00
result2 = buildImage ( name , build . WithoutCache , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
result2 . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2015-01-15 14:49:48 +00:00
// Skip over the times
2017-01-16 10:30:14 +00:00
e1 = removeLogTimestamps ( result1 . Error . Error ( ) )
e2 = removeLogTimestamps ( result2 . Error . Error ( ) )
2015-01-15 14:49:48 +00:00
// Ignore whitespace since that's what were verifying doesn't change stuff
if strings . Replace ( e1 , " " , "" , - 1 ) != strings . Replace ( e2 , " " , "" , - 1 ) {
2017-01-16 10:30:14 +00:00
c . Fatalf ( "Build 3's error wasn't the same as build 1's\n1:%s\n3:%s" , result1 . Error , result2 . Error )
2015-01-15 14:49:48 +00:00
}
2015-02-08 03:30:44 +00:00
ctx . Add ( "Dockerfile" , "FROM busybox\n COPY " )
2017-03-23 17:35:22 +00:00
result2 = buildImage ( name , build . WithoutCache , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
result2 . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2015-01-15 14:49:48 +00:00
// Skip over the times
2017-01-16 10:30:14 +00:00
e1 = removeLogTimestamps ( result1 . Error . Error ( ) )
e2 = removeLogTimestamps ( result2 . Error . Error ( ) )
2015-01-15 14:49:48 +00:00
// Ignore whitespace since that's what were verifying doesn't change stuff
if strings . Replace ( e1 , " " , "" , - 1 ) != strings . Replace ( e2 , " " , "" , - 1 ) {
2017-01-16 10:30:14 +00:00
c . Fatalf ( "Build 4's error wasn't the same as build 1's\n1:%s\n4:%s" , result1 . Error , result2 . Error )
2015-01-15 14:49:48 +00:00
}
}
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildSpacesWithQuotes ( c * check . C ) {
2015-01-15 14:49:48 +00:00
// Test to make sure that spaces in quotes aren't lost
name := "testspacesquotes"
dockerfile := ` FROM busybox
RUN echo " \
foo " `
2017-01-10 18:16:25 +00:00
expected := "\n foo \n"
2016-10-07 00:18:42 +00:00
// Windows uses the builtin echo, which preserves quotes
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2017-01-10 18:16:25 +00:00
expected = "\" foo \""
2015-01-15 14:49:48 +00:00
}
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( dockerfile ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
Out : expected ,
} )
2015-01-15 14:49:48 +00:00
}
2015-01-15 03:30:28 +00:00
// #4393
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildVolumeFileExistsinContainer ( c * check . C ) {
2016-02-09 02:12:04 +00:00
testRequires ( c , DaemonIsLinux ) // TODO Windows: This should error out
2017-03-23 17:35:22 +00:00
buildImage ( "docker-test-errcreatevolumewithfile" , build . WithDockerfile ( `
2015-01-15 03:30:28 +00:00
FROM busybox
RUN touch / foo
VOLUME / foo
2017-01-10 18:16:25 +00:00
` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "file exists" ,
} )
2015-01-15 03:30:28 +00:00
}
2015-02-04 17:34:25 +00:00
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) should be a unit test
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildMissingArgs ( c * check . C ) {
2015-02-08 03:30:44 +00:00
// Test to make sure that all Dockerfile commands (except the ones listed
// in skipCmds) will generate an error if no args are provided.
// Note: INSERT is deprecated so we exclude it because of that.
skipCmds := map [ string ] struct { } {
"CMD" : { } ,
"RUN" : { } ,
"ENTRYPOINT" : { } ,
"INSERT" : { } ,
2015-02-04 17:34:25 +00:00
}
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-09 02:12:04 +00:00
skipCmds = map [ string ] struct { } {
"CMD" : { } ,
"RUN" : { } ,
"ENTRYPOINT" : { } ,
"INSERT" : { } ,
"STOPSIGNAL" : { } ,
"ARG" : { } ,
"USER" : { } ,
"EXPOSE" : { } ,
}
}
2015-02-20 10:38:55 +00:00
for cmd := range command . Commands {
2015-02-08 03:30:44 +00:00
cmd = strings . ToUpper ( cmd )
if _ , ok := skipCmds [ cmd ] ; ok {
continue
}
2015-02-12 05:18:48 +00:00
var dockerfile string
2015-02-04 17:34:25 +00:00
if cmd == "FROM" {
dockerfile = cmd
} else {
// Add FROM to make sure we don't complain about it missing
dockerfile = "FROM busybox\n" + cmd
}
2017-03-23 17:35:22 +00:00
buildImage ( "args" , build . WithDockerfile ( dockerfile ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 1 ,
Err : cmd + " requires" ,
} )
2015-02-04 17:34:25 +00:00
}
}
2015-02-10 19:10:10 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEmptyScratch ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2017-03-23 17:35:22 +00:00
buildImage ( "sc" , build . WithDockerfile ( "FROM scratch" ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 1 ,
Err : "No image was generated" ,
} )
2015-02-10 19:10:10 +00:00
}
2015-02-17 02:38:52 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildDotDotFile ( c * check . C ) {
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , "sc" , withBuildContext ( c ,
withFile ( "Dockerfile" , "FROM busybox\n" ) ,
withFile ( "..gitme" , "" ) ,
) )
2015-02-17 02:38:52 +00:00
}
2015-02-20 21:26:11 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildRUNoneJSON ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // No hello-world Windows image
2015-03-09 21:44:14 +00:00
name := "testbuildrunonejson"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM hello - world : frozen
2017-01-10 18:16:25 +00:00
RUN [ "/hello" ] ` ) ) . Assert ( c , icmd . Expected {
Out : "Hello from Docker" ,
} )
2015-03-09 21:44:14 +00:00
}
2015-02-06 14:33:01 +00:00
2015-04-18 16:46:47 +00:00
func ( s * DockerSuite ) TestBuildEmptyStringVolume ( c * check . C ) {
2015-03-21 04:39:49 +00:00
name := "testbuildemptystringvolume"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( `
2015-03-21 04:39:49 +00:00
FROM busybox
ENV foo = ""
VOLUME $ foo
2017-01-10 18:16:25 +00:00
` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
} )
2015-03-21 04:39:49 +00:00
}
2015-03-28 02:18:24 +00:00
2015-04-25 20:42:30 +00:00
func ( s * DockerSuite ) TestBuildContainerWithCgroupParent ( c * check . C ) {
2017-01-10 18:16:25 +00:00
testRequires ( c , SameHostDaemon , DaemonIsLinux )
2015-03-28 02:18:24 +00:00
cgroupParent := "test"
data , err := ioutil . ReadFile ( "/proc/self/cgroup" )
if err != nil {
2015-04-25 20:42:30 +00:00
c . Fatalf ( "failed to read '/proc/self/cgroup - %v" , err )
2015-03-28 02:18:24 +00:00
}
2016-12-30 17:23:00 +00:00
selfCgroupPaths := testutil . ParseCgroupPaths ( string ( data ) )
2015-03-28 02:18:24 +00:00
_ , found := selfCgroupPaths [ "memory" ]
if ! found {
2015-07-29 18:46:33 +00:00
c . Fatalf ( "unable to find self memory cgroup path. CgroupsPath: %v" , selfCgroupPaths )
2015-03-28 02:18:24 +00:00
}
2017-01-16 10:30:14 +00:00
result := buildImage ( "buildcgroupparent" ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--cgroup-parent" , cgroupParent ) ,
build . WithDockerfile ( `
2015-03-28 02:18:24 +00:00
FROM busybox
RUN cat / proc / self / cgroup
2017-01-10 18:16:25 +00:00
` ) )
result . Assert ( c , icmd . Success )
m , err := regexp . MatchString ( fmt . Sprintf ( "memory:.*/%s/.*" , cgroupParent ) , result . Combined ( ) )
2015-07-29 18:46:33 +00:00
c . Assert ( err , check . IsNil )
if ! m {
2017-01-10 18:16:25 +00:00
c . Fatalf ( "There is no expected memory cgroup with parent /%s/: %s" , cgroupParent , result . Combined ( ) )
2015-07-29 18:46:33 +00:00
}
2015-03-28 02:18:24 +00:00
}
2015-05-05 21:27:42 +00:00
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) could be a unit test
2015-05-05 21:27:42 +00:00
func ( s * DockerSuite ) TestBuildNoDupOutput ( c * check . C ) {
// Check to make sure our build output prints the Dockerfile cmd
// property - there was a bug that caused it to be duplicated on the
// Step X line
name := "testbuildnodupoutput"
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithDockerfile ( `
2015-05-05 21:27:42 +00:00
FROM busybox
2017-01-10 18:16:25 +00:00
RUN env ` ) )
result . Assert ( c , icmd . Success )
2016-07-24 08:06:10 +00:00
exp := "\nStep 2/2 : RUN env\n"
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , exp ) {
c . Fatalf ( "Bad output\nGot:%s\n\nExpected to contain:%s\n" , result . Combined ( ) , exp )
2015-08-25 17:05:46 +00:00
}
}
// GH15826
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) could be a unit test
2015-08-25 17:05:46 +00:00
func ( s * DockerSuite ) TestBuildStartsFromOne ( c * check . C ) {
// Explicit check to ensure that build starts from step 1 rather than 0
name := "testbuildstartsfromone"
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithDockerfile ( ` FROM busybox ` ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Success )
2016-07-24 08:06:10 +00:00
exp := "\nStep 1/1 : FROM busybox\n"
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , exp ) {
c . Fatalf ( "Bad output\nGot:%s\n\nExpected to contain:%s\n" , result . Combined ( ) , exp )
2015-05-05 21:27:42 +00:00
}
}
2015-05-05 20:00:20 +00:00
func ( s * DockerSuite ) TestBuildRUNErrMsg ( c * check . C ) {
// Test to make sure the bad command is quoted with just "s and
// not as a Go []string
name := "testbuildbadrunerrmsg"
2016-02-12 00:20:27 +00:00
shell := "/bin/sh -c"
2017-01-10 18:16:25 +00:00
exitCode := 127
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-12 00:20:27 +00:00
shell = "cmd /S /C"
// architectural - Windows has to start the container to determine the exe is bad, Linux does not
2017-01-10 18:16:25 +00:00
exitCode = 1
2015-05-05 20:00:20 +00:00
}
2017-01-10 18:16:25 +00:00
exp := fmt . Sprintf ( ` The command '%s badEXE a1 \& a2 a3' returned a non-zero code: %d ` , shell , exitCode )
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( `
2017-01-10 18:16:25 +00:00
FROM busybox
RUN badEXE a1 \ & a2 a3 ` ) ) . Assert ( c , icmd . Expected {
ExitCode : exitCode ,
Err : exp ,
} )
2015-05-05 20:00:20 +00:00
}
2015-07-23 12:12:36 +00:00
func ( s * DockerTrustSuite ) TestTrustedBuild ( c * check . C ) {
repoName := s . setupTrustedImage ( c , "trusted-build" )
dockerFile := fmt . Sprintf ( `
FROM % s
RUN [ ]
` , repoName )
name := "testtrustedbuild"
2017-03-23 17:35:22 +00:00
buildImage ( name , trustedBuild , build . WithDockerfile ( dockerFile ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
Out : fmt . Sprintf ( "FROM %s@sha" , repoName [ : len ( repoName ) - 7 ] ) ,
} )
2015-07-23 12:12:36 +00:00
2015-07-24 23:35:11 +00:00
// We should also have a tag reference for the image.
2017-01-10 18:16:25 +00:00
dockerCmd ( c , "inspect" , repoName )
2015-07-24 23:35:11 +00:00
// We should now be able to remove the tag reference.
2017-01-10 18:16:25 +00:00
dockerCmd ( c , "rmi" , repoName )
2015-07-23 12:12:36 +00:00
}
func ( s * DockerTrustSuite ) TestTrustedBuildUntrustedTag ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockercli/build-untrusted-tag:latest" , privateRegistryURL )
dockerFile := fmt . Sprintf ( `
FROM % s
RUN [ ]
` , repoName )
name := "testtrustedbuilduntrustedtag"
2017-03-23 17:35:22 +00:00
buildImage ( name , trustedBuild , build . WithDockerfile ( dockerFile ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 1 ,
Err : "does not have trust data for" ,
} )
2015-07-23 12:12:36 +00:00
}
2015-07-27 17:21:36 +00:00
func ( s * DockerTrustSuite ) TestBuildContextDirIsSymlink ( c * check . C ) {
2015-08-28 17:36:42 +00:00
testRequires ( c , DaemonIsLinux )
2015-07-27 17:21:36 +00:00
tempDir , err := ioutil . TempDir ( "" , "test-build-dir-is-symlink-" )
2015-09-20 22:00:55 +00:00
c . Assert ( err , check . IsNil )
2015-07-27 17:21:36 +00:00
defer os . RemoveAll ( tempDir )
// Make a real context directory in this temp directory with a simple
// Dockerfile.
realContextDirname := filepath . Join ( tempDir , "context" )
if err := os . Mkdir ( realContextDirname , os . FileMode ( 0755 ) ) ; err != nil {
c . Fatal ( err )
}
if err = ioutil . WriteFile (
filepath . Join ( realContextDirname , "Dockerfile" ) ,
[ ] byte ( `
FROM busybox
RUN echo hello world
` ) ,
os . FileMode ( 0644 ) ,
) ; err != nil {
c . Fatal ( err )
}
// Make a symlink to the real context directory.
contextSymlinkName := filepath . Join ( tempDir , "context_link" )
if err := os . Symlink ( realContextDirname , contextSymlinkName ) ; err != nil {
c . Fatal ( err )
}
// Executing the build with the symlink as the specified context should
// *not* fail.
2017-01-10 18:16:25 +00:00
dockerCmd ( c , "build" , contextSymlinkName )
2015-07-27 17:21:36 +00:00
}
2015-08-17 17:22:57 +00:00
2016-03-17 02:59:18 +00:00
func ( s * DockerTrustSuite ) TestTrustedBuildTagFromReleasesRole ( c * check . C ) {
testRequires ( c , NotaryHosting )
latestTag := s . setupTrustedImage ( c , "trusted-build-releases-role" )
repoName := strings . TrimSuffix ( latestTag , ":latest" )
// Now create the releases role
s . notaryCreateDelegation ( c , repoName , "targets/releases" , s . not . keys [ 0 ] . Public )
s . notaryImportKey ( c , repoName , "targets/releases" , s . not . keys [ 0 ] . Private )
s . notaryPublish ( c , repoName )
// push a different tag to the releases role
otherTag := fmt . Sprintf ( "%s:other" , repoName )
dockerCmd ( c , "tag" , "busybox" , otherTag )
2017-01-05 18:08:24 +00:00
icmd . RunCmd ( icmd . Command ( dockerBinary , "push" , otherTag ) , trustedCmd ) . Assert ( c , icmd . Success )
2016-03-17 02:59:18 +00:00
s . assertTargetInRoles ( c , repoName , "other" , "targets/releases" )
s . assertTargetNotInRoles ( c , repoName , "other" , "targets" )
out , status := dockerCmd ( c , "rmi" , otherTag )
c . Assert ( status , check . Equals , 0 , check . Commentf ( "docker rmi failed: %s" , out ) )
dockerFile := fmt . Sprintf ( `
FROM % s
RUN [ ]
` , otherTag )
name := "testtrustedbuildreleasesrole"
2017-03-23 17:35:22 +00:00
buildImage ( name , trustedBuild , build . WithDockerfile ( dockerFile ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
Out : fmt . Sprintf ( "FROM %s@sha" , repoName ) ,
} )
2016-03-17 02:59:18 +00:00
}
func ( s * DockerTrustSuite ) TestTrustedBuildTagIgnoresOtherDelegationRoles ( c * check . C ) {
testRequires ( c , NotaryHosting )
latestTag := s . setupTrustedImage ( c , "trusted-build-releases-role" )
repoName := strings . TrimSuffix ( latestTag , ":latest" )
// Now create a non-releases delegation role
s . notaryCreateDelegation ( c , repoName , "targets/other" , s . not . keys [ 0 ] . Public )
s . notaryImportKey ( c , repoName , "targets/other" , s . not . keys [ 0 ] . Private )
s . notaryPublish ( c , repoName )
// push a different tag to the other role
otherTag := fmt . Sprintf ( "%s:other" , repoName )
dockerCmd ( c , "tag" , "busybox" , otherTag )
2017-01-05 18:08:24 +00:00
icmd . RunCmd ( icmd . Command ( dockerBinary , "push" , otherTag ) , trustedCmd ) . Assert ( c , icmd . Success )
2016-03-17 02:59:18 +00:00
s . assertTargetInRoles ( c , repoName , "other" , "targets/other" )
s . assertTargetNotInRoles ( c , repoName , "other" , "targets" )
out , status := dockerCmd ( c , "rmi" , otherTag )
c . Assert ( status , check . Equals , 0 , check . Commentf ( "docker rmi failed: %s" , out ) )
dockerFile := fmt . Sprintf ( `
FROM % s
RUN [ ]
` , otherTag )
name := "testtrustedbuildotherrole"
2017-03-23 17:35:22 +00:00
buildImage ( name , trustedBuild , build . WithDockerfile ( dockerFile ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 1 ,
} )
2016-03-17 02:59:18 +00:00
}
2015-08-17 17:22:57 +00:00
// Issue #15634: COPY fails when path starts with "null"
func ( s * DockerSuite ) TestBuildNullStringInAddCopyVolume ( c * check . C ) {
name := "testbuildnullstringinaddcopyvolume"
2016-02-12 00:20:27 +00:00
volName := "nullvolume"
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-12 00:20:27 +00:00
volName = ` C:\\nullvolume `
}
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , `
2015-08-17 17:22:57 +00:00
FROM busybox
2015-09-29 14:01:57 +00:00
2015-08-17 17:22:57 +00:00
ADD null /
COPY nullfile /
2016-02-12 00:20:27 +00:00
VOLUME ` +volName+ `
2017-01-10 18:16:25 +00:00
` ) ,
withFile ( "null" , "test1" ) ,
withFile ( "nullfile" , "test2" ) ,
) )
2015-08-17 17:22:57 +00:00
}
2015-08-18 17:30:44 +00:00
func ( s * DockerSuite ) TestBuildStopSignal ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support STOPSIGNAL yet
2016-02-12 22:56:40 +00:00
imgName := "test_build_stop_signal"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , imgName , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
STOPSIGNAL SIGKILL ` ) )
2016-02-12 22:56:40 +00:00
res := inspectFieldJSON ( c , imgName , "Config.StopSignal" )
if res != ` "SIGKILL" ` {
c . Fatalf ( "Signal %s, expected SIGKILL" , res )
}
containerName := "test-container-stop-signal"
dockerCmd ( c , "run" , "-d" , "--name" , containerName , imgName , "top" )
res = inspectFieldJSON ( c , containerName , "Config.StopSignal" )
2015-08-18 17:30:44 +00:00
if res != ` "SIGKILL" ` {
c . Fatalf ( "Signal %s, expected SIGKILL" , res )
}
}
2014-11-14 18:59:14 +00:00
func ( s * DockerSuite ) TestBuildBuildTimeArg ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
2016-05-04 18:06:54 +00:00
var dockerfile string
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-05-04 18:06:54 +00:00
// Bugs in Windows busybox port - use the default base image and native cmd stuff
dockerfile = fmt . Sprintf ( ` FROM ` + minimalBaseImage ( ) + `
ARG % s
RUN echo % % % s % %
CMD setlocal enableextensions && if defined % s ( echo % % % s % % ) ` , envKey , envKey , envKey , envKey )
} else {
dockerfile = fmt . Sprintf ( ` FROM busybox
ARG % s
RUN echo $ % s
CMD echo $ % s ` , envKey , envKey , envKey )
2014-11-14 18:59:14 +00:00
}
2017-01-16 10:30:14 +00:00
buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
) . Assert ( c , icmd . Expected {
Out : envVal ,
} )
2014-11-14 18:59:14 +00:00
containerName := "bldargCont"
2016-05-04 18:06:54 +00:00
out , _ := dockerCmd ( c , "run" , "--name" , containerName , imgName )
out = strings . Trim ( out , " \r\n'" )
if out != "" {
2014-11-14 18:59:14 +00:00
c . Fatalf ( "run produced invalid output: %q, expected empty string" , out )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgHistory ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
envDef := "bar1"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s = % s ` , envKey , envDef )
2017-01-16 10:30:14 +00:00
buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
) . Assert ( c , icmd . Expected {
Out : envVal ,
} )
2014-11-14 18:59:14 +00:00
out , _ := dockerCmd ( c , "history" , "--no-trunc" , imgName )
outputTabs := strings . Split ( out , "\n" ) [ 1 ]
if ! strings . Contains ( outputTabs , envDef ) {
c . Fatalf ( "failed to find arg default in image history output: %q expected: %q" , outputTabs , envDef )
}
}
2017-03-06 14:46:15 +00:00
func ( s * DockerSuite ) TestBuildTimeArgHistoryExclusions ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
proxy := "HTTP_PROXY=http://user:password@proxy.example.com"
explicitProxyKey := "http_proxy"
explicitProxyVal := "http://user:password@someproxy.example.com"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s
ARG % s
RUN echo "Testing Build Args!" ` , envKey , explicitProxyKey )
buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ,
2017-03-06 14:46:15 +00:00
"--build-arg" , fmt . Sprintf ( "%s=%s" , explicitProxyKey , explicitProxyVal ) ,
"--build-arg" , proxy ) ,
2017-03-23 17:35:22 +00:00
build . WithDockerfile ( dockerfile ) ,
2017-03-06 14:46:15 +00:00
) . Assert ( c , icmd . Success )
out , _ := dockerCmd ( c , "history" , "--no-trunc" , imgName )
if strings . Contains ( out , proxy ) {
c . Fatalf ( "failed to exclude proxy settings from history!" )
}
if ! strings . Contains ( out , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) {
c . Fatalf ( "explicitly defined ARG %s is not in output" , explicitProxyKey )
}
if ! strings . Contains ( out , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) {
c . Fatalf ( "missing build arguments from output" )
}
}
2014-11-14 18:59:14 +00:00
func ( s * DockerSuite ) TestBuildBuildTimeArgCacheHit ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s
RUN echo $ % s ` , envKey , envKey )
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
2017-01-16 10:30:14 +00:00
origImgID := getIDByName ( c , imgName )
2014-11-14 18:59:14 +00:00
imgNameCache := "bldargtestcachehit"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , imgNameCache ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
2017-01-16 10:30:14 +00:00
newImgID := getIDByName ( c , imgName )
2017-01-10 18:16:25 +00:00
if newImgID != origImgID {
2014-11-14 18:59:14 +00:00
c . Fatalf ( "build didn't use cache! expected image id: %q built image id: %q" , origImgID , newImgID )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgCacheMissExtraArg ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
extraEnvKey := "foo1"
extraEnvVal := "bar1"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s
ARG % s
RUN echo $ % s ` , envKey , extraEnvKey , envKey )
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
2017-01-16 10:30:14 +00:00
origImgID := getIDByName ( c , imgName )
2014-11-14 18:59:14 +00:00
imgNameCache := "bldargtestcachemiss"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , imgNameCache ,
2017-03-23 17:35:22 +00:00
cli . WithFlags (
2017-01-10 18:16:25 +00:00
"--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ,
"--build-arg" , fmt . Sprintf ( "%s=%s" , extraEnvKey , extraEnvVal ) ,
) ,
2017-03-23 17:35:22 +00:00
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
2017-01-16 10:30:14 +00:00
newImgID := getIDByName ( c , imgNameCache )
2017-01-10 18:16:25 +00:00
if newImgID == origImgID {
2014-11-14 18:59:14 +00:00
c . Fatalf ( "build used cache, expected a miss!" )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgCacheMissSameArgDiffVal ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
newEnvVal := "bar1"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s
RUN echo $ % s ` , envKey , envKey )
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
2017-01-16 10:30:14 +00:00
origImgID := getIDByName ( c , imgName )
2014-11-14 18:59:14 +00:00
imgNameCache := "bldargtestcachemiss"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , imgNameCache ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , newEnvVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
2017-01-16 10:30:14 +00:00
newImgID := getIDByName ( c , imgNameCache )
2017-01-10 18:16:25 +00:00
if newImgID == origImgID {
2014-11-14 18:59:14 +00:00
c . Fatalf ( "build used cache, expected a miss!" )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgOverrideArgDefinedBeforeEnv ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
2014-11-14 18:59:14 +00:00
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
envValOveride := "barOverride"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s
ENV % s % s
RUN echo $ % s
CMD echo $ % s
` , envKey , envKey , envValOveride , envKey , envKey )
2017-01-16 10:30:14 +00:00
result := buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
result . Assert ( c , icmd . Success )
if strings . Count ( result . Combined ( ) , envValOveride ) != 2 {
c . Fatalf ( "failed to access environment variable in output: %q expected: %q" , result . Combined ( ) , envValOveride )
2014-11-14 18:59:14 +00:00
}
containerName := "bldargCont"
if out , _ := dockerCmd ( c , "run" , "--name" , containerName , imgName ) ; ! strings . Contains ( out , envValOveride ) {
c . Fatalf ( "run produced invalid output: %q, expected %q" , out , envValOveride )
}
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) might be useful to merge with the one above ?
2014-11-14 18:59:14 +00:00
func ( s * DockerSuite ) TestBuildBuildTimeArgOverrideEnvDefinedBeforeArg ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
2014-11-14 18:59:14 +00:00
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
envValOveride := "barOverride"
dockerfile := fmt . Sprintf ( ` FROM busybox
ENV % s % s
ARG % s
RUN echo $ % s
CMD echo $ % s
` , envKey , envValOveride , envKey , envKey , envKey )
2017-01-16 10:30:14 +00:00
result := buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
result . Assert ( c , icmd . Success )
if strings . Count ( result . Combined ( ) , envValOveride ) != 2 {
c . Fatalf ( "failed to access environment variable in output: %q expected: %q" , result . Combined ( ) , envValOveride )
2014-11-14 18:59:14 +00:00
}
containerName := "bldargCont"
if out , _ := dockerCmd ( c , "run" , "--name" , containerName , imgName ) ; ! strings . Contains ( out , envValOveride ) {
c . Fatalf ( "run produced invalid output: %q, expected %q" , out , envValOveride )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgExpansion ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
2014-11-14 18:59:14 +00:00
imgName := "bldvarstest"
wdVar := "WDIR"
wdVal := "/tmp/"
addVar := "AFILE"
addVal := "addFile"
copyVar := "CFILE"
copyVal := "copyFile"
envVar := "foo"
envVal := "bar"
exposeVar := "EPORT"
exposeVal := "9999"
userVar := "USER"
userVal := "testUser"
volVar := "VOL"
volVal := "/testVol/"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags (
2017-01-10 18:16:25 +00:00
"--build-arg" , fmt . Sprintf ( "%s=%s" , wdVar , wdVal ) ,
"--build-arg" , fmt . Sprintf ( "%s=%s" , addVar , addVal ) ,
"--build-arg" , fmt . Sprintf ( "%s=%s" , copyVar , copyVal ) ,
"--build-arg" , fmt . Sprintf ( "%s=%s" , envVar , envVal ) ,
"--build-arg" , fmt . Sprintf ( "%s=%s" , exposeVar , exposeVal ) ,
"--build-arg" , fmt . Sprintf ( "%s=%s" , userVar , userVal ) ,
"--build-arg" , fmt . Sprintf ( "%s=%s" , volVar , volVal ) ,
) ,
withBuildContext ( c ,
withFile ( "Dockerfile" , fmt . Sprintf ( ` FROM busybox
2014-11-14 18:59:14 +00:00
ARG % s
WORKDIR $ { % s }
ARG % s
ADD $ { % s } testDir /
ARG % s
COPY $ % s testDir /
ARG % s
ENV % s = $ { % s }
ARG % s
EXPOSE $ % s
ARG % s
USER $ % s
ARG % s
VOLUME $ { % s } ` ,
2017-01-10 18:16:25 +00:00
wdVar , wdVar , addVar , addVar , copyVar , copyVar , envVar , envVar ,
envVar , exposeVar , exposeVar , userVar , userVar , volVar , volVar ) ) ,
withFile ( addVal , "some stuff" ) ,
withFile ( copyVal , "some stuff" ) ,
) ,
)
2014-11-14 18:59:14 +00:00
2017-01-10 18:16:25 +00:00
res := inspectField ( c , imgName , "Config.WorkingDir" )
2016-01-14 19:56:59 +00:00
if res != filepath . ToSlash ( filepath . Clean ( wdVal ) ) {
c . Fatalf ( "Config.WorkingDir value mismatch. Expected: %s, got: %s" , filepath . ToSlash ( filepath . Clean ( wdVal ) ) , res )
2014-11-14 18:59:14 +00:00
}
2017-01-10 18:16:25 +00:00
var resArr [ ] string
inspectFieldAndUnmarshall ( c , imgName , "Config.Env" , & resArr )
2014-11-14 18:59:14 +00:00
found := false
for _ , v := range resArr {
if fmt . Sprintf ( "%s=%s" , envVar , envVal ) == v {
found = true
break
}
}
if ! found {
c . Fatalf ( "Config.Env value mismatch. Expected <key=value> to exist: %s=%s, got: %v" ,
envVar , envVal , resArr )
}
2017-01-10 18:16:25 +00:00
var resMap map [ string ] interface { }
inspectFieldAndUnmarshall ( c , imgName , "Config.ExposedPorts" , & resMap )
2014-11-14 18:59:14 +00:00
if _ , ok := resMap [ fmt . Sprintf ( "%s/tcp" , exposeVal ) ] ; ! ok {
c . Fatalf ( "Config.ExposedPorts value mismatch. Expected exposed port: %s/tcp, got: %v" , exposeVal , resMap )
}
2016-01-28 14:19:25 +00:00
res = inspectField ( c , imgName , "Config.User" )
2014-11-14 18:59:14 +00:00
if res != userVal {
c . Fatalf ( "Config.User value mismatch. Expected: %s, got: %s" , userVal , res )
}
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , imgName , "Config.Volumes" , & resMap )
2014-11-14 18:59:14 +00:00
if _ , ok := resMap [ volVal ] ; ! ok {
c . Fatalf ( "Config.Volumes value mismatch. Expected volume: %s, got: %v" , volVal , resMap )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgExpansionOverride ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
2014-11-14 18:59:14 +00:00
imgName := "bldvarstest"
envKey := "foo"
envVal := "bar"
envKey1 := "foo1"
envValOveride := "barOverride"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s
ENV % s % s
ENV % s $ { % s }
RUN echo $ % s
CMD echo $ % s ` , envKey , envKey , envValOveride , envKey1 , envKey , envKey1 , envKey1 )
2017-01-16 10:30:14 +00:00
result := buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
result . Assert ( c , icmd . Success )
if strings . Count ( result . Combined ( ) , envValOveride ) != 2 {
c . Fatalf ( "failed to access environment variable in output: %q expected: %q" , result . Combined ( ) , envValOveride )
2014-11-14 18:59:14 +00:00
}
containerName := "bldargCont"
if out , _ := dockerCmd ( c , "run" , "--name" , containerName , imgName ) ; ! strings . Contains ( out , envValOveride ) {
c . Fatalf ( "run produced invalid output: %q, expected %q" , out , envValOveride )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgUntrustedDefinedAfterUse ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
2014-11-14 18:59:14 +00:00
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
dockerfile := fmt . Sprintf ( ` FROM busybox
RUN echo $ % s
ARG % s
CMD echo $ % s ` , envKey , envKey , envKey )
2017-01-16 10:30:14 +00:00
result := buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
result . Assert ( c , icmd . Success )
if strings . Contains ( result . Combined ( ) , envVal ) {
c . Fatalf ( "able to access environment variable in output: %q expected to be missing" , result . Combined ( ) )
2014-11-14 18:59:14 +00:00
}
containerName := "bldargCont"
if out , _ := dockerCmd ( c , "run" , "--name" , containerName , imgName ) ; out != "\n" {
c . Fatalf ( "run produced invalid output: %q, expected empty string" , out )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgBuiltinArg ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support --build-arg
2014-11-14 18:59:14 +00:00
imgName := "bldargtest"
envKey := "HTTP_PROXY"
envVal := "bar"
dockerfile := fmt . Sprintf ( ` FROM busybox
RUN echo $ % s
CMD echo $ % s ` , envKey , envKey )
2017-01-16 10:30:14 +00:00
result := buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
result . Assert ( c , icmd . Success )
if ! strings . Contains ( result . Combined ( ) , envVal ) {
c . Fatalf ( "failed to access environment variable in output: %q expected: %q" , result . Combined ( ) , envVal )
2014-11-14 18:59:14 +00:00
}
containerName := "bldargCont"
if out , _ := dockerCmd ( c , "run" , "--name" , containerName , imgName ) ; out != "\n" {
c . Fatalf ( "run produced invalid output: %q, expected empty string" , out )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgDefaultOverride ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
2014-11-14 18:59:14 +00:00
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
envValOveride := "barOverride"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s = % s
ENV % s $ % s
RUN echo $ % s
CMD echo $ % s ` , envKey , envVal , envKey , envKey , envKey , envKey )
2017-01-16 10:30:14 +00:00
result := buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envValOveride ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
)
result . Assert ( c , icmd . Success )
if strings . Count ( result . Combined ( ) , envValOveride ) != 1 {
c . Fatalf ( "failed to access environment variable in output: %q expected: %q" , result . Combined ( ) , envValOveride )
2014-11-14 18:59:14 +00:00
}
containerName := "bldargCont"
if out , _ := dockerCmd ( c , "run" , "--name" , containerName , imgName ) ; ! strings . Contains ( out , envValOveride ) {
c . Fatalf ( "run produced invalid output: %q, expected %q" , out , envValOveride )
}
}
func ( s * DockerSuite ) TestBuildBuildTimeArgUnconsumedArg ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envVal := "bar"
dockerfile := fmt . Sprintf ( ` FROM busybox
RUN echo $ % s
CMD echo $ % s ` , envKey , envKey )
2016-10-16 03:37:15 +00:00
warnStr := "[Warning] One or more build-args"
2017-01-16 10:30:14 +00:00
buildImage ( imgName ,
2017-03-23 17:35:22 +00:00
cli . WithFlags ( "--build-arg" , fmt . Sprintf ( "%s=%s" , envKey , envVal ) ) ,
build . WithDockerfile ( dockerfile ) ,
2017-01-10 18:16:25 +00:00
) . Assert ( c , icmd . Expected {
Out : warnStr ,
} )
2014-11-14 18:59:14 +00:00
}
2017-01-10 18:16:25 +00:00
func ( s * DockerSuite ) TestBuildBuildTimeArgEnv ( c * check . C ) {
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
dockerfile := ` FROM busybox
2016-12-03 13:46:04 +00:00
ARG FOO1 = fromfile
ARG FOO2 = fromfile
ARG FOO3 = fromfile
ARG FOO4 = fromfile
ARG FOO5
ARG FOO6
2017-03-22 01:56:07 +00:00
ARG FO10
2016-12-03 13:46:04 +00:00
RUN env
RUN [ "$FOO1" == "fromcmd" ]
RUN [ "$FOO2" == "" ]
RUN [ "$FOO3" == "fromenv" ]
RUN [ "$FOO4" == "fromfile" ]
RUN [ "$FOO5" == "fromcmd" ]
# The following should not exist at all in the env
RUN [ "$(env | grep FOO6)" == "" ]
RUN [ "$(env | grep FOO7)" == "" ]
RUN [ "$(env | grep FOO8)" == "" ]
RUN [ "$(env | grep FOO9)" == "" ]
2017-03-22 01:56:07 +00:00
RUN [ "$FO10" == "" ]
2017-01-10 18:16:25 +00:00
`
2017-01-16 10:30:14 +00:00
result := buildImage ( "testbuildtimeargenv" ,
2017-03-23 17:35:22 +00:00
cli . WithFlags (
2017-01-10 18:16:25 +00:00
"--build-arg" , fmt . Sprintf ( "FOO1=fromcmd" ) ,
"--build-arg" , fmt . Sprintf ( "FOO2=" ) ,
"--build-arg" , fmt . Sprintf ( "FOO3" ) , // set in env
"--build-arg" , fmt . Sprintf ( "FOO4" ) , // not set in env
"--build-arg" , fmt . Sprintf ( "FOO5=fromcmd" ) ,
// FOO6 is not set at all
"--build-arg" , fmt . Sprintf ( "FOO7=fromcmd" ) , // should produce a warning
"--build-arg" , fmt . Sprintf ( "FOO8=" ) , // should produce a warning
"--build-arg" , fmt . Sprintf ( "FOO9" ) , // should produce a warning
2017-03-22 01:56:07 +00:00
"--build-arg" , fmt . Sprintf ( "FO10" ) , // not set in env, empty value
2017-01-10 18:16:25 +00:00
) ,
2017-03-23 17:35:22 +00:00
cli . WithEnvironmentVariables ( append ( os . Environ ( ) ,
2017-01-10 18:16:25 +00:00
"FOO1=fromenv" ,
"FOO2=fromenv" ,
"FOO3=fromenv" ) ... ) ,
withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
) ,
)
result . Assert ( c , icmd . Success )
2016-12-03 13:46:04 +00:00
// Now check to make sure we got a warning msg about unused build-args
2017-01-10 18:16:25 +00:00
i := strings . Index ( result . Combined ( ) , "[Warning]" )
2016-12-03 13:46:04 +00:00
if i < 0 {
2017-01-10 18:16:25 +00:00
c . Fatalf ( "Missing the build-arg warning in %q" , result . Combined ( ) )
2016-12-03 13:46:04 +00:00
}
2017-01-10 18:16:25 +00:00
out := result . Combined ( ) [ i : ] // "out" should contain just the warning message now
2016-12-03 13:46:04 +00:00
// These were specified on a --build-arg but no ARG was in the Dockerfile
c . Assert ( out , checker . Contains , "FOO7" )
c . Assert ( out , checker . Contains , "FOO8" )
c . Assert ( out , checker . Contains , "FOO9" )
}
2014-11-14 18:59:14 +00:00
func ( s * DockerSuite ) TestBuildBuildTimeArgQuotedValVariants ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
envKey1 := "foo1"
envKey2 := "foo2"
envKey3 := "foo3"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s = ""
ARG % s = ' '
ARG % s = "''"
ARG % s = ' "" '
RUN [ "$%s" != "$%s" ]
RUN [ "$%s" != "$%s" ]
RUN [ "$%s" != "$%s" ]
RUN [ "$%s" != "$%s" ]
RUN [ "$%s" != "$%s" ] ` , envKey , envKey1 , envKey2 , envKey3 ,
envKey , envKey2 , envKey , envKey3 , envKey1 , envKey2 , envKey1 , envKey3 ,
envKey2 , envKey3 )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , imgName , build . WithDockerfile ( dockerfile ) )
2014-11-14 18:59:14 +00:00
}
func ( s * DockerSuite ) TestBuildBuildTimeArgEmptyValVariants ( c * check . C ) {
2016-02-12 00:20:27 +00:00
testRequires ( c , DaemonIsLinux ) // Windows does not support ARG
2014-11-14 18:59:14 +00:00
imgName := "bldargtest"
envKey := "foo"
envKey1 := "foo1"
envKey2 := "foo2"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s =
ARG % s = ""
ARG % s = ' '
RUN [ "$%s" == "$%s" ]
RUN [ "$%s" == "$%s" ]
RUN [ "$%s" == "$%s" ] ` , envKey , envKey1 , envKey2 , envKey , envKey1 , envKey1 , envKey2 , envKey , envKey2 )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , imgName , build . WithDockerfile ( dockerfile ) )
2014-11-14 18:59:14 +00:00
}
func ( s * DockerSuite ) TestBuildBuildTimeArgDefintionWithNoEnvInjection ( c * check . C ) {
imgName := "bldargtest"
envKey := "foo"
dockerfile := fmt . Sprintf ( ` FROM busybox
ARG % s
RUN env ` , envKey )
2017-03-23 17:35:22 +00:00
result := buildImage ( imgName , build . WithDockerfile ( dockerfile ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Success )
if strings . Count ( result . Combined ( ) , envKey ) != 1 {
c . Fatalf ( "unexpected number of occurrences of the arg in output: %q expected: 1" , result . Combined ( ) )
2014-11-14 18:59:14 +00:00
}
}
2015-09-29 14:01:57 +00:00
2017-03-16 21:31:02 +00:00
func ( s * DockerSuite ) TestBuildBuildTimeArgMultipleFrom ( c * check . C ) {
imgName := "multifrombldargtest"
dockerfile := ` FROM busybox
ARG foo = abc
LABEL multifromtest = 1
RUN env > / out
FROM busybox
ARG bar = def
RUN env > / out `
2017-03-24 07:27:32 +00:00
result := buildImage ( imgName , build . WithDockerfile ( dockerfile ) )
2017-03-16 21:31:02 +00:00
result . Assert ( c , icmd . Success )
result = icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "images" , "-q" , "-f" , "label=multifromtest=1" } ,
} )
result . Assert ( c , icmd . Success )
parentID := strings . TrimSpace ( result . Stdout ( ) )
result = icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "--rm" , parentID , "cat" , "/out" } ,
} )
result . Assert ( c , icmd . Success )
c . Assert ( result . Stdout ( ) , checker . Contains , "foo=abc" )
result = icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "--rm" , imgName , "cat" , "/out" } ,
} )
result . Assert ( c , icmd . Success )
c . Assert ( result . Stdout ( ) , checker . Not ( checker . Contains ) , "foo" )
c . Assert ( result . Stdout ( ) , checker . Contains , "bar=def" )
}
func ( s * DockerSuite ) TestBuildBuildTimeUnusedArgMultipleFrom ( c * check . C ) {
imgName := "multifromunusedarg"
dockerfile := ` FROM busybox
ARG foo
FROM busybox
ARG bar
RUN env > / out `
2017-03-24 07:27:32 +00:00
result := buildImage ( imgName , build . WithDockerfile ( dockerfile ) , cli . WithFlags (
2017-03-16 21:31:02 +00:00
"--build-arg" , fmt . Sprintf ( "baz=abc" ) ) )
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , checker . Contains , "[Warning]" )
c . Assert ( result . Combined ( ) , checker . Contains , "[baz] were not consumed" )
result = icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "run" , "--rm" , imgName , "cat" , "/out" } ,
} )
result . Assert ( c , icmd . Success )
c . Assert ( result . Stdout ( ) , checker . Not ( checker . Contains ) , "bar" )
c . Assert ( result . Stdout ( ) , checker . Not ( checker . Contains ) , "baz" )
}
2015-09-29 14:01:57 +00:00
func ( s * DockerSuite ) TestBuildNoNamedVolume ( c * check . C ) {
2016-02-12 00:20:27 +00:00
volName := "testname:/foo"
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2016-02-12 00:20:27 +00:00
volName = "testname:C:\\foo"
}
dockerCmd ( c , "run" , "-v" , volName , "busybox" , "sh" , "-c" , "touch /foo/oops" )
2015-09-29 14:01:57 +00:00
dockerFile := ` FROM busybox
2016-02-12 00:20:27 +00:00
VOLUME ` + volName + `
2015-09-29 14:01:57 +00:00
RUN ls / foo / oops
`
2017-03-23 17:35:22 +00:00
buildImage ( "test" , build . WithDockerfile ( dockerFile ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 1 ,
} )
2015-09-29 14:01:57 +00:00
}
2015-10-16 15:54:05 +00:00
func ( s * DockerSuite ) TestBuildTagEvent ( c * check . C ) {
2016-04-11 18:52:34 +00:00
since := daemonUnixTime ( c )
2015-10-16 15:54:05 +00:00
dockerFile := ` FROM busybox
RUN echo events
`
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "test" , build . WithDockerfile ( dockerFile ) )
2015-10-16 15:54:05 +00:00
2016-04-11 18:52:34 +00:00
until := daemonUnixTime ( c )
out , _ := dockerCmd ( c , "events" , "--since" , since , "--until" , until , "--filter" , "type=image" )
2015-12-21 22:55:23 +00:00
events := strings . Split ( strings . TrimSpace ( out ) , "\n" )
actions := eventActionsByIDAndType ( c , events , "test:latest" , "image" )
var foundTag bool
for _ , a := range actions {
if a == "tag" {
foundTag = true
break
2015-12-21 20:34:08 +00:00
}
}
2015-12-21 22:55:23 +00:00
c . Assert ( foundTag , checker . True , check . Commentf ( "No tag event found:\n%s" , out ) )
2015-10-16 15:54:05 +00:00
}
2015-08-30 13:48:03 +00:00
// #15780
func ( s * DockerSuite ) TestBuildMultipleTags ( c * check . C ) {
dockerfile := `
FROM busybox
MAINTAINER test - 15780
`
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "tag1" , cli . WithFlags ( "-t" , "tag2:v2" , "-t" , "tag1:latest" , "-t" , "tag1" ) , build . WithDockerfile ( dockerfile ) )
2015-08-30 13:48:03 +00:00
2017-01-16 10:30:14 +00:00
id1 := getIDByName ( c , "tag1" )
id2 := getIDByName ( c , "tag2:v2" )
2015-08-30 13:48:03 +00:00
c . Assert ( id1 , check . Equals , id2 )
}
2015-11-04 21:42:08 +00:00
// #17290
func ( s * DockerSuite ) TestBuildCacheBrokenSymlink ( c * check . C ) {
name := "testbuildbrokensymlink"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , `
2015-11-04 21:42:08 +00:00
FROM busybox
COPY . . / ` ,
map [ string ] string {
"foo" : "bar" ,
} )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
err := os . Symlink ( filepath . Join ( ctx . Dir , "nosuchfile" ) , filepath . Join ( ctx . Dir , "asymlink" ) )
2015-11-04 21:42:08 +00:00
c . Assert ( err , checker . IsNil )
// warm up cache
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2015-11-04 21:42:08 +00:00
// add new file to context, should invalidate cache
err = ioutil . WriteFile ( filepath . Join ( ctx . Dir , "newfile" ) , [ ] byte ( "foo" ) , 0644 )
c . Assert ( err , checker . IsNil )
2017-01-16 10:30:14 +00:00
result := buildImage ( name , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
if strings . Contains ( result . Combined ( ) , "Using cache" ) {
c . Fatal ( "2nd build used cache on ADD, it shouldn't" )
}
2015-11-04 21:42:08 +00:00
}
func ( s * DockerSuite ) TestBuildFollowSymlinkToFile ( c * check . C ) {
name := "testbuildbrokensymlink"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , `
2015-11-04 21:42:08 +00:00
FROM busybox
COPY asymlink target ` ,
map [ string ] string {
"foo" : "bar" ,
} )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
err := os . Symlink ( "foo" , filepath . Join ( ctx . Dir , "asymlink" ) )
2015-11-04 21:42:08 +00:00
c . Assert ( err , checker . IsNil )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2015-11-04 21:42:08 +00:00
2017-01-16 10:30:14 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , name , "cat" , "target" )
2015-11-04 21:42:08 +00:00
c . Assert ( out , checker . Matches , "bar" )
// change target file should invalidate cache
err = ioutil . WriteFile ( filepath . Join ( ctx . Dir , "foo" ) , [ ] byte ( "baz" ) , 0644 )
c . Assert ( err , checker . IsNil )
2017-01-16 10:30:14 +00:00
result := buildImage ( name , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , checker . Not ( checker . Contains ) , "Using cache" )
2015-11-04 21:42:08 +00:00
2017-01-16 10:30:14 +00:00
out , _ = dockerCmd ( c , "run" , "--rm" , name , "cat" , "target" )
2015-11-04 21:42:08 +00:00
c . Assert ( out , checker . Matches , "baz" )
}
func ( s * DockerSuite ) TestBuildFollowSymlinkToDir ( c * check . C ) {
name := "testbuildbrokensymlink"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , `
2015-11-04 21:42:08 +00:00
FROM busybox
COPY asymlink / ` ,
map [ string ] string {
"foo/abc" : "bar" ,
"foo/def" : "baz" ,
} )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
err := os . Symlink ( "foo" , filepath . Join ( ctx . Dir , "asymlink" ) )
2015-11-04 21:42:08 +00:00
c . Assert ( err , checker . IsNil )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2015-11-04 21:42:08 +00:00
2017-01-16 10:30:14 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , name , "cat" , "abc" , "def" )
2015-11-04 21:42:08 +00:00
c . Assert ( out , checker . Matches , "barbaz" )
// change target file should invalidate cache
err = ioutil . WriteFile ( filepath . Join ( ctx . Dir , "foo/def" ) , [ ] byte ( "bax" ) , 0644 )
c . Assert ( err , checker . IsNil )
2017-01-16 10:30:14 +00:00
result := buildImage ( name , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , checker . Not ( checker . Contains ) , "Using cache" )
2015-11-04 21:42:08 +00:00
2017-01-16 10:30:14 +00:00
out , _ = dockerCmd ( c , "run" , "--rm" , name , "cat" , "abc" , "def" )
2015-11-04 21:42:08 +00:00
c . Assert ( out , checker . Matches , "barbax" )
}
// TestBuildSymlinkBasename tests that target file gets basename from symlink,
// not from the target file.
func ( s * DockerSuite ) TestBuildSymlinkBasename ( c * check . C ) {
name := "testbuildbrokensymlink"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , `
2015-11-04 21:42:08 +00:00
FROM busybox
COPY asymlink / ` ,
map [ string ] string {
"foo" : "bar" ,
} )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
err := os . Symlink ( "foo" , filepath . Join ( ctx . Dir , "asymlink" ) )
2015-11-04 21:42:08 +00:00
c . Assert ( err , checker . IsNil )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2015-11-04 21:42:08 +00:00
2017-01-16 10:30:14 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , name , "cat" , "asymlink" )
2015-11-04 21:42:08 +00:00
c . Assert ( out , checker . Matches , "bar" )
}
2015-11-10 18:14:05 +00:00
// #17827
func ( s * DockerSuite ) TestBuildCacheRootSource ( c * check . C ) {
name := "testbuildrootsource"
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , `
2015-11-10 18:14:05 +00:00
FROM busybox
COPY / / data ` ,
map [ string ] string {
"foo" : "bar" ,
} )
defer ctx . Close ( )
// warm up cache
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , name , withExternalBuildContext ( ctx ) )
2015-11-10 18:14:05 +00:00
// change file, should invalidate cache
2017-01-16 10:30:14 +00:00
err := ioutil . WriteFile ( filepath . Join ( ctx . Dir , "foo" ) , [ ] byte ( "baz" ) , 0644 )
2015-11-10 18:14:05 +00:00
c . Assert ( err , checker . IsNil )
2017-01-16 10:30:14 +00:00
result := buildImage ( name , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
2015-11-10 18:14:05 +00:00
2017-01-16 10:30:14 +00:00
c . Assert ( result . Combined ( ) , checker . Not ( checker . Contains ) , "Using cache" )
2015-11-10 18:14:05 +00:00
}
2016-01-16 10:59:13 +00:00
// #19375
func ( s * DockerSuite ) TestBuildFailsGitNotCallable ( c * check . C ) {
2017-03-23 17:35:22 +00:00
buildImage ( "gitnotcallable" , cli . WithEnvironmentVariables ( "PATH=" ) ,
build . WithContextPath ( "github.com/docker/v1.10-migrator.git" ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 1 ,
Err : "unable to prepare context: unable to find 'git': " ,
} )
2016-01-16 10:59:13 +00:00
2017-03-23 17:35:22 +00:00
buildImage ( "gitnotcallable" , cli . WithEnvironmentVariables ( "PATH=" ) ,
build . WithContextPath ( "https://github.com/docker/v1.10-migrator.git" ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
ExitCode : 1 ,
Err : "unable to prepare context: unable to find 'git': " ,
} )
2016-01-16 10:59:13 +00:00
}
2016-01-27 21:03:09 +00:00
// TestBuildWorkdirWindowsPath tests that a Windows style path works as a workdir
func ( s * DockerSuite ) TestBuildWorkdirWindowsPath ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
name := "testbuildworkdirwindowspath"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2017-01-13 16:23:28 +00:00
FROM ` +testEnv.MinimalBaseImage()+ `
2016-01-27 21:03:09 +00:00
RUN mkdir C : \ \ work
WORKDIR C : \ \ work
RUN if "%CD%" NEQ "C:\work" exit - 1
2017-01-10 18:16:25 +00:00
` ) )
2016-01-27 21:03:09 +00:00
}
2016-02-12 17:08:45 +00:00
2016-03-16 21:52:34 +00:00
func ( s * DockerSuite ) TestBuildLabel ( c * check . C ) {
name := "testbuildlabel"
testLabel := "foo"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , testLabel ) ,
build . WithDockerfile ( `
2016-03-16 21:52:34 +00:00
FROM ` +minimalBaseImage()+ `
LABEL default foo
2017-01-10 18:16:25 +00:00
` ) )
2016-03-16 21:52:34 +00:00
var labels map [ string ] string
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.Labels" , & labels )
2016-03-16 21:52:34 +00:00
if _ , ok := labels [ testLabel ] ; ! ok {
c . Fatal ( "label not found in image" )
}
}
2016-03-30 21:26:02 +00:00
func ( s * DockerSuite ) TestBuildLabelOneNode ( c * check . C ) {
name := "testbuildlabel"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , "foo=bar" ) ,
build . WithDockerfile ( "FROM busybox" ) )
2016-03-30 21:26:02 +00:00
var labels map [ string ] string
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.Labels" , & labels )
2016-03-30 21:26:02 +00:00
v , ok := labels [ "foo" ]
if ! ok {
c . Fatal ( "label `foo` not found in image" )
}
c . Assert ( v , checker . Equals , "bar" )
}
2016-03-16 21:52:34 +00:00
func ( s * DockerSuite ) TestBuildLabelCacheCommit ( c * check . C ) {
name := "testbuildlabelcachecommit"
testLabel := "foo"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2016-03-16 21:52:34 +00:00
FROM ` +minimalBaseImage()+ `
LABEL default foo
2017-01-10 18:16:25 +00:00
` ) )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , testLabel ) ,
build . WithDockerfile ( `
2016-03-16 21:52:34 +00:00
FROM ` +minimalBaseImage()+ `
LABEL default foo
2017-01-10 18:16:25 +00:00
` ) )
2016-03-16 21:52:34 +00:00
var labels map [ string ] string
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.Labels" , & labels )
2016-03-16 21:52:34 +00:00
if _ , ok := labels [ testLabel ] ; ! ok {
c . Fatal ( "label not found in image" )
}
}
func ( s * DockerSuite ) TestBuildLabelMultiple ( c * check . C ) {
name := "testbuildlabelmultiple"
testLabels := map [ string ] string {
"foo" : "bar" ,
"123" : "456" ,
}
labelArgs := [ ] string { }
for k , v := range testLabels {
labelArgs = append ( labelArgs , "--label" , k + "=" + v )
}
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( labelArgs ... ) ,
build . WithDockerfile ( `
2016-03-16 21:52:34 +00:00
FROM ` +minimalBaseImage()+ `
LABEL default foo
2017-01-10 18:16:25 +00:00
` ) )
2016-03-16 21:52:34 +00:00
var labels map [ string ] string
2017-01-10 18:16:25 +00:00
inspectFieldAndUnmarshall ( c , name , "Config.Labels" , & labels )
2016-03-16 21:52:34 +00:00
for k , v := range testLabels {
if x , ok := labels [ k ] ; ! ok || x != v {
c . Fatalf ( "label %s=%s not found in image" , k , v )
}
}
}
2016-03-14 20:11:35 +00:00
func ( s * DockerRegistryAuthHtpasswdSuite ) TestBuildFromAuthenticatedRegistry ( c * check . C ) {
2016-12-30 18:10:04 +00:00
dockerCmd ( c , "login" , "-u" , s . reg . Username ( ) , "-p" , s . reg . Password ( ) , privateRegistryURL )
2016-02-12 17:08:45 +00:00
baseImage := privateRegistryURL + "/baseimage"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , baseImage , build . WithDockerfile ( `
2016-02-12 17:08:45 +00:00
FROM busybox
ENV env1 val1
2017-01-10 18:16:25 +00:00
` ) )
2016-02-12 17:08:45 +00:00
dockerCmd ( c , "push" , baseImage )
dockerCmd ( c , "rmi" , baseImage )
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , baseImage , build . WithDockerfile ( fmt . Sprintf ( `
2016-02-12 17:08:45 +00:00
FROM % s
ENV env2 val2
2017-01-10 18:16:25 +00:00
` , baseImage ) ) )
2016-02-12 17:08:45 +00:00
}
2016-03-01 17:04:35 +00:00
2016-03-14 20:11:35 +00:00
func ( s * DockerRegistryAuthHtpasswdSuite ) TestBuildWithExternalAuth ( c * check . C ) {
2016-03-01 17:04:35 +00:00
osPath := os . Getenv ( "PATH" )
defer os . Setenv ( "PATH" , osPath )
workingDir , err := os . Getwd ( )
c . Assert ( err , checker . IsNil )
absolute , err := filepath . Abs ( filepath . Join ( workingDir , "fixtures" , "auth" ) )
c . Assert ( err , checker . IsNil )
testPath := fmt . Sprintf ( "%s%c%s" , osPath , filepath . ListSeparator , absolute )
os . Setenv ( "PATH" , testPath )
repoName := fmt . Sprintf ( "%v/dockercli/busybox:authtest" , privateRegistryURL )
tmp , err := ioutil . TempDir ( "" , "integration-cli-" )
c . Assert ( err , checker . IsNil )
externalAuthConfig := ` { "credsStore": "shell-test" } `
configPath := filepath . Join ( tmp , "config.json" )
err = ioutil . WriteFile ( configPath , [ ] byte ( externalAuthConfig ) , 0644 )
c . Assert ( err , checker . IsNil )
2016-12-30 18:10:04 +00:00
dockerCmd ( c , "--config" , tmp , "login" , "-u" , s . reg . Username ( ) , "-p" , s . reg . Password ( ) , privateRegistryURL )
2016-03-01 17:04:35 +00:00
b , err := ioutil . ReadFile ( configPath )
c . Assert ( err , checker . IsNil )
c . Assert ( string ( b ) , checker . Not ( checker . Contains ) , "\"auth\":" )
dockerCmd ( c , "--config" , tmp , "tag" , "busybox" , repoName )
dockerCmd ( c , "--config" , tmp , "push" , repoName )
// make sure the image is pulled when building
dockerCmd ( c , "rmi" , repoName )
2017-01-10 18:16:25 +00:00
icmd . RunCmd ( icmd . Cmd {
Command : [ ] string { dockerBinary , "--config" , tmp , "build" , "-" } ,
Stdin : strings . NewReader ( fmt . Sprintf ( "FROM %s" , repoName ) ) ,
} ) . Assert ( c , icmd . Success )
2016-03-01 17:04:35 +00:00
}
2016-04-23 19:59:17 +00:00
// Test cases in #22036
func ( s * DockerSuite ) TestBuildLabelsOverride ( c * check . C ) {
// Command line option labels will always override
name := "scratchy"
expected := ` { "bar":"from-flag","foo":"from-flag"} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , "foo=from-flag" , "--label" , "bar=from-flag" ) ,
build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
LABEL foo = from - dockerfile ` ) )
2016-04-23 19:59:17 +00:00
res := inspectFieldJSON ( c , name , "Config.Labels" )
if res != expected {
c . Fatalf ( "Labels %s, expected %s" , res , expected )
}
name = "from"
expected = ` { "foo":"from-dockerfile"} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
LABEL foo from - dockerfile ` ) )
2016-04-23 19:59:17 +00:00
res = inspectFieldJSON ( c , name , "Config.Labels" )
if res != expected {
c . Fatalf ( "Labels %s, expected %s" , res , expected )
}
// Command line option label will override even via `FROM`
name = "new"
expected = ` { "bar":"from-dockerfile2","foo":"new"} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , "foo=new" ) ,
build . WithDockerfile ( ` FROM from
2017-01-10 18:16:25 +00:00
LABEL bar from - dockerfile2 ` ) )
2016-04-23 19:59:17 +00:00
res = inspectFieldJSON ( c , name , "Config.Labels" )
if res != expected {
c . Fatalf ( "Labels %s, expected %s" , res , expected )
}
// Command line option without a value set (--label foo, --label bar=)
// will be treated as --label foo="", --label bar=""
name = "scratchy2"
expected = ` { "bar":"","foo":""} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , "foo" , "--label" , "bar=" ) ,
build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
LABEL foo = from - dockerfile ` ) )
2016-04-23 19:59:17 +00:00
res = inspectFieldJSON ( c , name , "Config.Labels" )
if res != expected {
c . Fatalf ( "Labels %s, expected %s" , res , expected )
}
// Command line option without a value set (--label foo, --label bar=)
// will be treated as --label foo="", --label bar=""
// This time is for inherited images
name = "new2"
expected = ` { "bar":"","foo":""} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , "foo=" , "--label" , "bar" ) ,
build . WithDockerfile ( ` FROM from
2017-01-10 18:16:25 +00:00
LABEL bar from - dockerfile2 ` ) )
2016-04-23 19:59:17 +00:00
res = inspectFieldJSON ( c , name , "Config.Labels" )
if res != expected {
c . Fatalf ( "Labels %s, expected %s" , res , expected )
}
// Command line option labels with only `FROM`
name = "scratchy"
expected = ` { "bar":"from-flag","foo":"from-flag"} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , "foo=from-flag" , "--label" , "bar=from-flag" ) ,
build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) ) )
2016-04-23 19:59:17 +00:00
res = inspectFieldJSON ( c , name , "Config.Labels" )
if res != expected {
c . Fatalf ( "Labels %s, expected %s" , res , expected )
}
2016-10-06 01:15:46 +00:00
// Command line option labels with env var
name = "scratchz"
expected = ` { "bar":"$PATH"} `
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--label" , "bar=$PATH" ) ,
build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) ) )
2016-10-06 01:15:46 +00:00
res = inspectFieldJSON ( c , name , "Config.Labels" )
2016-04-23 19:59:17 +00:00
if res != expected {
c . Fatalf ( "Labels %s, expected %s" , res , expected )
}
}
2016-05-31 19:51:29 +00:00
// Test case for #22855
func ( s * DockerSuite ) TestBuildDeleteCommittedFile ( c * check . C ) {
name := "test-delete-committed-file"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2016-05-31 19:51:29 +00:00
RUN echo test > file
RUN test - e file
RUN rm file
2017-01-10 18:16:25 +00:00
RUN sh - c "! test -e file" ` ) )
2016-05-31 19:51:29 +00:00
}
2016-06-01 22:20:54 +00:00
// #20083
func ( s * DockerSuite ) TestBuildDockerignoreComment ( c * check . C ) {
2016-06-03 20:23:35 +00:00
// TODO Windows: Figure out why this test is flakey on TP5. If you add
// something like RUN sleep 5, or even RUN ls /tmp after the ADD line,
// it is more reliable, but that's not a good fix.
testRequires ( c , DaemonIsLinux )
2016-06-01 22:20:54 +00:00
name := "testbuilddockerignorecleanpaths"
dockerfile := `
FROM busybox
ADD . / tmp /
RUN sh - c "(ls -la /tmp/#1)"
RUN sh - c "(! ls -la /tmp/#2)"
RUN sh - c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (ls /tmp/dir1/foo)" `
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( "foo" , "foo" ) ,
withFile ( "foo2" , "foo2" ) ,
withFile ( "dir1/foo" , "foo in dir1" ) ,
withFile ( "#1" , "# file 1" ) ,
withFile ( "#2" , "# file 2" ) ,
withFile ( ".dockerignore" , ` # Visual C ++ cache files
2016-06-01 22:20:54 +00:00
# because we have git ; - )
# The above comment is from # 20083
foo
# dir1 / foo
foo2
# The following is considered as comment as # is at the beginning
# 1
# The following is not considered as comment as # is not at the beginning
# 2
2017-01-10 18:16:25 +00:00
` ) ) )
2016-06-01 22:20:54 +00:00
}
2016-06-03 12:32:37 +00:00
// Test case for #23221
func ( s * DockerSuite ) TestBuildWithUTF8BOM ( c * check . C ) {
name := "test-with-utf8-bom"
dockerfile := [ ] byte ( ` FROM busybox ` )
bomDockerfile := append ( [ ] byte { 0xEF , 0xBB , 0xBF } , dockerfile ... )
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , string ( bomDockerfile ) ) ,
) )
2016-06-03 12:32:37 +00:00
}
2016-06-03 14:26:36 +00:00
// Test case for UTF-8 BOM in .dockerignore, related to #23221
func ( s * DockerSuite ) TestBuildWithUTF8BOMDockerignore ( c * check . C ) {
name := "test-with-utf8-bom-dockerignore"
dockerfile := `
FROM busybox
ADD . / tmp /
RUN ls - la / tmp
RUN sh - c "! ls /tmp/Dockerfile"
RUN ls / tmp / . dockerignore `
dockerignore := [ ] byte ( "./Dockerfile\n" )
bomDockerignore := append ( [ ] byte { 0xEF , 0xBB , 0xBF } , dockerignore ... )
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , dockerfile ) ,
withFile ( ".dockerignore" , string ( bomDockerignore ) ) ,
) )
2016-06-03 14:26:36 +00:00
}
2016-05-03 20:56:59 +00:00
// #22489 Shell test to confirm config gets updated correctly
func ( s * DockerSuite ) TestBuildShellUpdatesConfig ( c * check . C ) {
name := "testbuildshellupdatesconfig"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2017-01-10 18:16:25 +00:00
SHELL [ "foo" , "-bar" ] ` ) )
2016-05-03 20:56:59 +00:00
expected := ` ["foo","-bar","#(nop) ","SHELL [foo -bar]"] `
res := inspectFieldJSON ( c , name , "ContainerConfig.Cmd" )
if res != expected {
c . Fatalf ( "%s, expected %s" , res , expected )
}
res = inspectFieldJSON ( c , name , "ContainerConfig.Shell" )
if res != ` ["foo","-bar"] ` {
c . Fatalf ( ` %s, expected ["foo","-bar"] ` , res )
}
}
// #22489 Changing the shell multiple times and CMD after.
func ( s * DockerSuite ) TestBuildShellMultiple ( c * check . C ) {
name := "testbuildshellmultiple"
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithDockerfile ( ` FROM busybox
2016-05-03 20:56:59 +00:00
RUN echo defaultshell
SHELL [ "echo" ]
RUN echoshell
SHELL [ "ls" ]
RUN - l
2017-01-10 18:16:25 +00:00
CMD - l ` ) )
result . Assert ( c , icmd . Success )
2016-05-03 20:56:59 +00:00
// Must contain 'defaultshell' twice
2017-01-10 18:16:25 +00:00
if len ( strings . Split ( result . Combined ( ) , "defaultshell" ) ) != 3 {
c . Fatalf ( "defaultshell should have appeared twice in %s" , result . Combined ( ) )
2016-05-03 20:56:59 +00:00
}
// Must contain 'echoshell' twice
2017-01-10 18:16:25 +00:00
if len ( strings . Split ( result . Combined ( ) , "echoshell" ) ) != 3 {
c . Fatalf ( "echoshell should have appeared twice in %s" , result . Combined ( ) )
2016-05-03 20:56:59 +00:00
}
// Must contain "total " (part of ls -l)
2017-01-10 18:16:25 +00:00
if ! strings . Contains ( result . Combined ( ) , "total " ) {
c . Fatalf ( "%s should have contained 'total '" , result . Combined ( ) )
2016-05-03 20:56:59 +00:00
}
// A container started from the image uses the shell-form CMD.
// Last shell is ls. CMD is -l. So should contain 'total '.
outrun , _ := dockerCmd ( c , "run" , "--rm" , name )
if ! strings . Contains ( outrun , "total " ) {
c . Fatalf ( "Expected started container to run ls -l. %s" , outrun )
}
}
// #22489. Changed SHELL with ENTRYPOINT
func ( s * DockerSuite ) TestBuildShellEntrypoint ( c * check . C ) {
name := "testbuildshellentrypoint"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( ` FROM busybox
2016-05-03 20:56:59 +00:00
SHELL [ "ls" ]
2017-01-10 18:16:25 +00:00
ENTRYPOINT - l ` ) )
2016-05-03 20:56:59 +00:00
// A container started from the image uses the shell-form ENTRYPOINT.
// Shell is ls. ENTRYPOINT is -l. So should contain 'total '.
outrun , _ := dockerCmd ( c , "run" , "--rm" , name )
if ! strings . Contains ( outrun , "total " ) {
c . Fatalf ( "Expected started container to run ls -l. %s" , outrun )
}
}
// #22489 Shell test to confirm shell is inherited in a subsequent build
func ( s * DockerSuite ) TestBuildShellInherited ( c * check . C ) {
name1 := "testbuildshellinherited1"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name1 , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
SHELL [ "ls" ] ` ) )
2016-05-03 20:56:59 +00:00
name2 := "testbuildshellinherited2"
2017-03-23 17:35:22 +00:00
buildImage ( name2 , build . WithDockerfile ( ` FROM ` + name1 + `
2017-01-10 18:16:25 +00:00
RUN - l ` ) ) . Assert ( c , icmd . Expected {
// ls -l has "total " followed by some number in it, ls without -l does not.
Out : "total " ,
} )
2016-05-03 20:56:59 +00:00
}
// #22489 Shell test to confirm non-JSON doesn't work
func ( s * DockerSuite ) TestBuildShellNotJSON ( c * check . C ) {
name := "testbuildshellnotjson"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2016-05-03 20:56:59 +00:00
sHeLl exec - form ` , // Casing explicit to ensure error is upper-cased.
2017-01-10 18:16:25 +00:00
) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "SHELL requires the arguments to be in JSON form" ,
} )
2016-05-03 20:56:59 +00:00
}
// #22489 Windows shell test to confirm native is powershell if executing a PS command
// This would error if the default shell were still cmd.
func ( s * DockerSuite ) TestBuildShellWindowsPowershell ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
name := "testbuildshellpowershell"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM ` + minimalBaseImage ( ) + `
2016-05-03 20:56:59 +00:00
SHELL [ "powershell" , "-command" ]
2017-01-10 18:16:25 +00:00
RUN Write - Host John ` ) ) . Assert ( c , icmd . Expected {
Out : "\nJohn\n" ,
} )
2016-05-03 20:56:59 +00:00
}
2016-05-20 23:05:14 +00:00
2016-10-21 18:55:39 +00:00
// Verify that escape is being correctly applied to words when escape directive is not \.
// Tests WORKDIR, ADD
func ( s * DockerSuite ) TestBuildEscapeNotBackslashWordTest ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
name := "testbuildescapenotbackslashwordtesta"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` # escape= ` + "`" + `
2016-10-21 18:55:39 +00:00
FROM ` +minimalBaseImage()+ `
WORKDIR c : \ windows
2017-01-10 18:16:25 +00:00
RUN dir / w ` ) ) . Assert ( c , icmd . Expected {
Out : "[System32]" ,
} )
2016-10-21 18:55:39 +00:00
name = "testbuildescapenotbackslashwordtestb"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` # escape= ` + "`" + `
2016-10-21 18:55:39 +00:00
FROM ` +minimalBaseImage()+ `
SHELL [ "powershell.exe" ]
WORKDIR c : \ foo
ADD Dockerfile c : \ foo \
2017-01-10 18:16:25 +00:00
RUN dir Dockerfile ` ) ) . Assert ( c , icmd . Expected {
Out : "-a----" ,
} )
2016-10-21 18:55:39 +00:00
}
2016-05-20 23:05:14 +00:00
// #22868. Make sure shell-form CMD is marked as escaped in the config of the image
func ( s * DockerSuite ) TestBuildCmdShellArgsEscaped ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
name := "testbuildcmdshellescaped"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2016-05-20 23:05:14 +00:00
FROM ` +minimalBaseImage()+ `
2016-07-22 17:36:51 +00:00
CMD "ipconfig"
2017-01-10 18:16:25 +00:00
` ) )
2016-05-20 23:05:14 +00:00
res := inspectFieldJSON ( c , name , "Config.ArgsEscaped" )
if res != "true" {
c . Fatalf ( "CMD did not update Config.ArgsEscaped on image: %v" , res )
}
dockerCmd ( c , "run" , "--name" , "inspectme" , name )
dockerCmd ( c , "wait" , "inspectme" )
res = inspectFieldJSON ( c , name , "Config.Cmd" )
2016-07-22 17:36:51 +00:00
if res != ` ["cmd","/S","/C","\"ipconfig\""] ` {
2016-05-20 23:05:14 +00:00
c . Fatalf ( "CMD was not escaped Config.Cmd: got %v" , res )
}
}
2016-07-24 08:06:10 +00:00
// Test case for #24912.
func ( s * DockerSuite ) TestBuildStepsWithProgress ( c * check . C ) {
name := "testbuildstepswithprogress"
totalRun := 5
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithDockerfile ( "FROM busybox\n" + strings . Repeat ( "RUN echo foo\n" , totalRun ) ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , checker . Contains , fmt . Sprintf ( "Step 1/%d : FROM busybox" , 1 + totalRun ) )
2016-07-24 08:06:10 +00:00
for i := 2 ; i <= 1 + totalRun ; i ++ {
2017-01-10 18:16:25 +00:00
c . Assert ( result . Combined ( ) , checker . Contains , fmt . Sprintf ( "Step %d/%d : RUN echo foo" , i , 1 + totalRun ) )
2016-07-24 08:06:10 +00:00
}
}
2016-09-13 04:06:04 +00:00
func ( s * DockerSuite ) TestBuildWithFailure ( c * check . C ) {
name := "testbuildwithfailure"
// First test case can only detect `nobody` in runtime so all steps will show up
2017-01-10 18:16:25 +00:00
dockerfile := "FROM busybox\nRUN nobody"
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithDockerfile ( dockerfile ) )
2017-01-10 18:16:25 +00:00
c . Assert ( result . Error , checker . NotNil )
c . Assert ( result . Stdout ( ) , checker . Contains , "Step 1/2 : FROM busybox" )
c . Assert ( result . Stdout ( ) , checker . Contains , "Step 2/2 : RUN nobody" )
2016-09-13 04:06:04 +00:00
// Second test case `FFOM` should have been detected before build runs so no steps
2017-01-10 18:16:25 +00:00
dockerfile = "FFOM nobody\nRUN nobody"
2017-03-23 17:35:22 +00:00
result = buildImage ( name , build . WithDockerfile ( dockerfile ) )
2017-01-10 18:16:25 +00:00
c . Assert ( result . Error , checker . NotNil )
c . Assert ( result . Stdout ( ) , checker . Not ( checker . Contains ) , "Step 1/2 : FROM busybox" )
c . Assert ( result . Stdout ( ) , checker . Not ( checker . Contains ) , "Step 2/2 : RUN nobody" )
2016-09-13 04:06:04 +00:00
}
2016-09-22 21:32:17 +00:00
2017-02-20 16:16:11 +00:00
func ( s * DockerSuite ) TestBuildCacheFromEqualDiffIDsLength ( c * check . C ) {
dockerfile := `
FROM busybox
RUN echo "test"
ENTRYPOINT [ "sh" ] `
ctx := fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
} )
defer ctx . Close ( )
buildImageSuccessfully ( c , "build1" , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , "build1" )
// rebuild with cache-from
2017-03-23 17:35:22 +00:00
result := buildImage ( "build2" , cli . WithFlags ( "--cache-from=build1" ) , withExternalBuildContext ( ctx ) )
2017-02-20 16:16:11 +00:00
result . Assert ( c , icmd . Success )
id2 := getIDByName ( c , "build2" )
c . Assert ( id1 , checker . Equals , id2 )
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 2 )
}
2016-09-22 21:32:17 +00:00
func ( s * DockerSuite ) TestBuildCacheFrom ( c * check . C ) {
testRequires ( c , DaemonIsLinux ) // All tests that do save are skipped in windows
dockerfile := `
FROM busybox
ENV FOO = bar
ADD baz /
RUN touch bax `
2017-01-16 10:30:14 +00:00
ctx := fakeContext ( c , dockerfile , map [ string ] string {
2016-09-22 21:32:17 +00:00
"Dockerfile" : dockerfile ,
"baz" : "baz" ,
} )
defer ctx . Close ( )
2017-01-16 10:30:14 +00:00
buildImageSuccessfully ( c , "build1" , withExternalBuildContext ( ctx ) )
id1 := getIDByName ( c , "build1" )
2016-09-22 21:32:17 +00:00
// rebuild with cache-from
2017-03-23 17:35:22 +00:00
result := buildImage ( "build2" , cli . WithFlags ( "--cache-from=build1" ) , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
result . Assert ( c , icmd . Success )
id2 := getIDByName ( c , "build2" )
2016-09-22 21:32:17 +00:00
c . Assert ( id1 , checker . Equals , id2 )
2017-01-16 10:30:14 +00:00
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 3 )
2016-09-22 21:32:17 +00:00
dockerCmd ( c , "rmi" , "build2" )
// no cache match with unknown source
2017-03-23 17:35:22 +00:00
result = buildImage ( "build2" , cli . WithFlags ( "--cache-from=nosuchtag" ) , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
result . Assert ( c , icmd . Success )
id2 = getIDByName ( c , "build2" )
2016-09-22 21:32:17 +00:00
c . Assert ( id1 , checker . Not ( checker . Equals ) , id2 )
2017-01-16 10:30:14 +00:00
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 0 )
2016-09-22 21:32:17 +00:00
dockerCmd ( c , "rmi" , "build2" )
// clear parent images
tempDir , err := ioutil . TempDir ( "" , "test-build-cache-from-" )
if err != nil {
c . Fatalf ( "failed to create temporary directory: %s" , tempDir )
}
defer os . RemoveAll ( tempDir )
tempFile := filepath . Join ( tempDir , "img.tar" )
dockerCmd ( c , "save" , "-o" , tempFile , "build1" )
dockerCmd ( c , "rmi" , "build1" )
dockerCmd ( c , "load" , "-i" , tempFile )
parentID , _ := dockerCmd ( c , "inspect" , "-f" , "{{.Parent}}" , "build1" )
c . Assert ( strings . TrimSpace ( parentID ) , checker . Equals , "" )
// cache still applies without parents
2017-03-23 17:35:22 +00:00
result = buildImage ( "build2" , cli . WithFlags ( "--cache-from=build1" ) , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
result . Assert ( c , icmd . Success )
id2 = getIDByName ( c , "build2" )
2016-09-22 21:32:17 +00:00
c . Assert ( id1 , checker . Equals , id2 )
2017-01-16 10:30:14 +00:00
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 3 )
2016-09-22 21:32:17 +00:00
history1 , _ := dockerCmd ( c , "history" , "-q" , "build2" )
// Retry, no new intermediate images
2017-03-23 17:35:22 +00:00
result = buildImage ( "build3" , cli . WithFlags ( "--cache-from=build1" ) , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
result . Assert ( c , icmd . Success )
id3 := getIDByName ( c , "build3" )
2016-09-22 21:32:17 +00:00
c . Assert ( id1 , checker . Equals , id3 )
2017-01-16 10:30:14 +00:00
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 3 )
2016-09-22 21:32:17 +00:00
history2 , _ := dockerCmd ( c , "history" , "-q" , "build3" )
c . Assert ( history1 , checker . Equals , history2 )
dockerCmd ( c , "rmi" , "build2" )
dockerCmd ( c , "rmi" , "build3" )
dockerCmd ( c , "rmi" , "build1" )
dockerCmd ( c , "load" , "-i" , tempFile )
// Modify file, everything up to last command and layers are reused
dockerfile = `
FROM busybox
ENV FOO = bar
ADD baz /
RUN touch newfile `
err = ioutil . WriteFile ( filepath . Join ( ctx . Dir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 )
c . Assert ( err , checker . IsNil )
2017-03-23 17:35:22 +00:00
result = buildImage ( "build2" , cli . WithFlags ( "--cache-from=build1" ) , withExternalBuildContext ( ctx ) )
2017-01-16 10:30:14 +00:00
result . Assert ( c , icmd . Success )
id2 = getIDByName ( c , "build2" )
2016-09-22 21:32:17 +00:00
c . Assert ( id1 , checker . Not ( checker . Equals ) , id2 )
2017-01-16 10:30:14 +00:00
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 2 )
2016-09-22 21:32:17 +00:00
layers1Str , _ := dockerCmd ( c , "inspect" , "-f" , "{{json .RootFS.Layers}}" , "build1" )
layers2Str , _ := dockerCmd ( c , "inspect" , "-f" , "{{json .RootFS.Layers}}" , "build2" )
var layers1 [ ] string
var layers2 [ ] string
c . Assert ( json . Unmarshal ( [ ] byte ( layers1Str ) , & layers1 ) , checker . IsNil )
c . Assert ( json . Unmarshal ( [ ] byte ( layers2Str ) , & layers2 ) , checker . IsNil )
c . Assert ( len ( layers1 ) , checker . Equals , len ( layers2 ) )
for i := 0 ; i < len ( layers1 ) - 1 ; i ++ {
c . Assert ( layers1 [ i ] , checker . Equals , layers2 [ i ] )
}
c . Assert ( layers1 [ len ( layers1 ) - 1 ] , checker . Not ( checker . Equals ) , layers2 [ len ( layers1 ) - 1 ] )
}
2016-10-24 23:28:14 +00:00
2017-03-16 23:17:49 +00:00
func ( s * DockerSuite ) TestBuildCacheMultipleFrom ( c * check . C ) {
testRequires ( c , DaemonIsLinux ) // All tests that do save are skipped in windows
dockerfile := `
FROM busybox
ADD baz /
FROM busybox
ADD baz / `
ctx := fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"baz" : "baz" ,
} )
defer ctx . Close ( )
result := buildImage ( "build1" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
// second part of dockerfile was a repeat of first so should be cached
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 1 )
2017-03-24 07:27:32 +00:00
result = buildImage ( "build2" , cli . WithFlags ( "--cache-from=build1" ) , withExternalBuildContext ( ctx ) )
2017-03-16 23:17:49 +00:00
result . Assert ( c , icmd . Success )
// now both parts of dockerfile should be cached
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 2 )
}
2016-10-24 23:28:14 +00:00
func ( s * DockerSuite ) TestBuildNetNone ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
name := "testbuildnetnone"
2017-03-23 17:35:22 +00:00
buildImage ( name , cli . WithFlags ( "--network=none" ) , build . WithDockerfile ( `
2016-10-24 23:28:14 +00:00
FROM busybox
RUN ping - c 1 8.8 .8 .8
2017-01-10 18:16:25 +00:00
` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Out : "unreachable" ,
} )
2016-10-24 23:28:14 +00:00
}
func ( s * DockerSuite ) TestBuildNetContainer ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
id , _ := dockerCmd ( c , "run" , "--hostname" , "foobar" , "-d" , "busybox" , "nc" , "-ll" , "-p" , "1234" , "-e" , "hostname" )
name := "testbuildnetcontainer"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--network=container:" + strings . TrimSpace ( id ) ) ,
build . WithDockerfile ( `
2016-10-24 23:28:14 +00:00
FROM busybox
RUN nc localhost 1234 > / otherhost
2017-01-10 18:16:25 +00:00
` ) )
2016-10-24 23:28:14 +00:00
host , _ := dockerCmd ( c , "run" , "testbuildnetcontainer" , "cat" , "/otherhost" )
c . Assert ( strings . TrimSpace ( host ) , check . Equals , "foobar" )
}
2016-07-16 19:37:16 +00:00
2017-01-13 15:01:58 +00:00
func ( s * DockerSuite ) TestBuildWithExtraHost ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
name := "testbuildwithextrahost"
buildImageSuccessfully ( c , name ,
2017-03-23 17:35:22 +00:00
cli . WithFlags (
2017-01-13 15:01:58 +00:00
"--add-host" , "foo:127.0.0.1" ,
"--add-host" , "bar:127.0.0.1" ,
) ,
2017-03-23 17:35:22 +00:00
build . WithDockerfile ( `
2017-01-13 15:01:58 +00:00
FROM busybox
RUN ping - c 1 foo
RUN ping - c 1 bar
` ) )
}
func ( s * DockerSuite ) TestBuildWithExtraHostInvalidFormat ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
dockerfile := `
FROM busybox
RUN ping - c 1 foo `
testCases := [ ] struct {
testName string
dockerfile string
buildFlag string
} {
{ "extra_host_missing_ip" , dockerfile , "--add-host=foo" } ,
{ "extra_host_missing_ip_with_delimeter" , dockerfile , "--add-host=foo:" } ,
{ "extra_host_missing_hostname" , dockerfile , "--add-host=:127.0.0.1" } ,
{ "extra_host_invalid_ipv4" , dockerfile , "--add-host=foo:101.10.2" } ,
{ "extra_host_invalid_ipv6" , dockerfile , "--add-host=foo:2001::1::3F" } ,
}
for _ , tc := range testCases {
2017-03-23 17:35:22 +00:00
result := buildImage ( tc . testName , cli . WithFlags ( tc . buildFlag ) , build . WithDockerfile ( tc . dockerfile ) )
2017-01-13 15:01:58 +00:00
result . Assert ( c , icmd . Expected {
ExitCode : 125 ,
} )
}
}
2016-04-21 16:08:37 +00:00
func ( s * DockerSuite ) TestBuildSquashParent ( c * check . C ) {
testRequires ( c , ExperimentalDaemon )
dockerFile := `
FROM busybox
RUN echo hello > / hello
RUN echo world >> / hello
RUN echo hello > / remove_me
ENV HELLO world
RUN rm / remove_me
`
// build and get the ID that we can use later for history comparison
2017-01-10 18:16:25 +00:00
name := "test"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerFile ) )
2017-01-16 10:30:14 +00:00
origID := getIDByName ( c , name )
2016-04-21 16:08:37 +00:00
// build with squash
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , cli . WithFlags ( "--squash" ) , build . WithDockerfile ( dockerFile ) )
2017-01-16 10:30:14 +00:00
id := getIDByName ( c , name )
2016-04-21 16:08:37 +00:00
out , _ := dockerCmd ( c , "run" , "--rm" , id , "/bin/sh" , "-c" , "cat /hello" )
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "hello\nworld" )
dockerCmd ( c , "run" , "--rm" , id , "/bin/sh" , "-c" , "[ ! -f /remove_me ]" )
dockerCmd ( c , "run" , "--rm" , id , "/bin/sh" , "-c" , ` [ "$(echo $HELLO)" == "world" ] ` )
// make sure the ID produced is the ID of the tag we specified
2017-01-16 15:39:12 +00:00
inspectID := inspectImage ( c , "test" , ".ID" )
2016-04-21 16:08:37 +00:00
c . Assert ( inspectID , checker . Equals , id )
origHistory , _ := dockerCmd ( c , "history" , origID )
testHistory , _ := dockerCmd ( c , "history" , "test" )
splitOrigHistory := strings . Split ( strings . TrimSpace ( origHistory ) , "\n" )
splitTestHistory := strings . Split ( strings . TrimSpace ( testHistory ) , "\n" )
c . Assert ( len ( splitTestHistory ) , checker . Equals , len ( splitOrigHistory ) + 1 )
2017-01-16 15:39:12 +00:00
out = inspectImage ( c , id , "len .RootFS.Layers" )
2016-04-21 16:08:37 +00:00
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , "3" )
}
2016-10-28 21:11:36 +00:00
func ( s * DockerSuite ) TestBuildContChar ( c * check . C ) {
name := "testbuildcontchar"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM busybox\ ` ) ) . Assert ( c , icmd . Expected {
2017-01-10 18:16:25 +00:00
Out : "Step 1/1 : FROM busybox" ,
} )
2016-10-28 21:11:36 +00:00
2017-03-23 17:35:22 +00:00
result := buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
RUN echo hi \ ` ) )
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , checker . Contains , "Step 1/2 : FROM busybox" )
c . Assert ( result . Combined ( ) , checker . Contains , "Step 2/2 : RUN echo hi\n" )
2016-10-28 21:11:36 +00:00
2017-03-23 17:35:22 +00:00
result = buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
RUN echo hi \ \ ` ) )
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , checker . Contains , "Step 1/2 : FROM busybox" )
c . Assert ( result . Combined ( ) , checker . Contains , "Step 2/2 : RUN echo hi \\\n" )
2016-10-28 21:11:36 +00:00
2017-03-23 17:35:22 +00:00
result = buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 18:16:25 +00:00
RUN echo hi \ \ \ ` ) )
result . Assert ( c , icmd . Success )
c . Assert ( result . Combined ( ) , checker . Contains , "Step 1/2 : FROM busybox" )
c . Assert ( result . Combined ( ) , checker . Contains , "Step 2/2 : RUN echo hi \\\\\n" )
2016-10-28 21:11:36 +00:00
}
2016-11-09 21:07:56 +00:00
2017-03-15 22:28:06 +00:00
func ( s * DockerSuite ) TestBuildCopyFromPreviousRootFS ( c * check . C ) {
dockerfile := `
2017-03-20 17:28:21 +00:00
FROM busybox AS first
2017-03-15 22:28:06 +00:00
COPY foo bar
FROM busybox
% s
COPY baz baz
RUN echo mno > baz / cc
FROM busybox
COPY bar /
COPY -- from = 1 baz sub /
COPY -- from = 0 bar baz
2017-03-20 17:28:21 +00:00
COPY -- from = first bar bay `
2017-03-15 22:28:06 +00:00
ctx := fakeContext ( c , fmt . Sprintf ( dockerfile , "" ) , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "abc" ,
"bar" : "def" ,
"baz/aa" : "ghi" ,
"baz/bb" : "jkl" ,
} )
defer ctx . Close ( )
result := buildImage ( "build1" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
out , _ := dockerCmd ( c , "run" , "build1" , "cat" , "bar" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "def" )
out , _ = dockerCmd ( c , "run" , "build1" , "cat" , "sub/aa" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "ghi" )
out , _ = dockerCmd ( c , "run" , "build1" , "cat" , "sub/cc" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "mno" )
out , _ = dockerCmd ( c , "run" , "build1" , "cat" , "baz" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "abc" )
out , _ = dockerCmd ( c , "run" , "build1" , "cat" , "bay" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "abc" )
result = buildImage ( "build2" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
// all commands should be cached
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 7 )
err := ioutil . WriteFile ( filepath . Join ( ctx . Dir , "Dockerfile" ) , [ ] byte ( fmt . Sprintf ( dockerfile , "COPY baz/aa foo" ) ) , 0644 )
c . Assert ( err , checker . IsNil )
// changing file in parent block should not affect last block
result = buildImage ( "build3" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 5 )
c . Assert ( getIDByName ( c , "build1" ) , checker . Equals , getIDByName ( c , "build2" ) )
err = ioutil . WriteFile ( filepath . Join ( ctx . Dir , "foo" ) , [ ] byte ( "pqr" ) , 0644 )
c . Assert ( err , checker . IsNil )
// changing file in parent block should affect both first and last block
result = buildImage ( "build4" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 5 )
out , _ = dockerCmd ( c , "run" , "build4" , "cat" , "bay" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "pqr" )
out , _ = dockerCmd ( c , "run" , "build4" , "cat" , "baz" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "pqr" )
}
func ( s * DockerSuite ) TestBuildCopyFromPreviousRootFSErrors ( c * check . C ) {
dockerfile := `
FROM busybox
COPY -- from = foo foo bar `
ctx := fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "abc" ,
} )
defer ctx . Close ( )
buildImage ( "build1" , withExternalBuildContext ( ctx ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
2017-03-23 00:49:39 +00:00
Err : "invalid from flag value foo" ,
2017-03-15 22:28:06 +00:00
} )
dockerfile = `
FROM busybox
COPY -- from = 0 foo bar `
ctx = fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "abc" ,
} )
defer ctx . Close ( )
buildImage ( "build1" , withExternalBuildContext ( ctx ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "invalid from flag value 0 refers current build block" ,
} )
2017-03-20 17:28:21 +00:00
dockerfile = `
FROM busybox AS foo
COPY -- from = bar foo bar `
ctx = fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "abc" ,
} )
defer ctx . Close ( )
buildImage ( "build1" , withExternalBuildContext ( ctx ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
2017-03-23 00:49:39 +00:00
Err : "invalid from flag value bar" ,
2017-03-20 17:28:21 +00:00
} )
dockerfile = `
FROM busybox AS 1
COPY -- from = 1 foo bar `
ctx = fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "abc" ,
} )
defer ctx . Close ( )
buildImage ( "build1" , withExternalBuildContext ( ctx ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "invalid name for build stage" ,
} )
2017-03-15 22:28:06 +00:00
}
func ( s * DockerSuite ) TestBuildCopyFromPreviousFrom ( c * check . C ) {
dockerfile := `
FROM busybox
COPY foo bar `
ctx := fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "abc" ,
} )
defer ctx . Close ( )
result := buildImage ( "build1" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
dockerfile = `
2017-03-20 17:28:21 +00:00
FROM build1 : latest AS foo
2017-03-15 22:28:06 +00:00
FROM busybox
2017-03-20 17:28:21 +00:00
COPY -- from = foo bar /
2017-03-15 22:28:06 +00:00
COPY foo / `
ctx = fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "def" ,
} )
defer ctx . Close ( )
result = buildImage ( "build2" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
out , _ := dockerCmd ( c , "run" , "build2" , "cat" , "bar" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "abc" )
out , _ = dockerCmd ( c , "run" , "build2" , "cat" , "foo" )
c . Assert ( strings . TrimSpace ( out ) , check . Equals , "def" )
}
2017-03-23 00:49:39 +00:00
func ( s * DockerSuite ) TestBuildCopyFromImplicitFrom ( c * check . C ) {
dockerfile := `
FROM busybox
COPY -- from = busybox / etc / passwd / mypasswd
RUN cmp / etc / passwd / mypasswd `
if DaemonIsWindows ( ) {
dockerfile = `
FROM busybox
COPY -- from = busybox License . txt foo `
}
ctx := fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
} )
defer ctx . Close ( )
result := buildImage ( "build1" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
if DaemonIsWindows ( ) {
out , _ := dockerCmd ( c , "run" , "build1" , "cat" , "License.txt" )
c . Assert ( len ( out ) , checker . GreaterThan , 10 )
out2 , _ := dockerCmd ( c , "run" , "build1" , "cat" , "foo" )
c . Assert ( out , check . Equals , out2 )
}
}
2017-03-23 01:36:08 +00:00
func ( s * DockerRegistrySuite ) TestBuildCopyFromImplicitPullingFrom ( c * check . C ) {
repoName := fmt . Sprintf ( "%v/dockercli/testf" , privateRegistryURL )
dockerfile := `
FROM busybox
COPY foo bar `
ctx := fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "abc" ,
} )
defer ctx . Close ( )
result := buildImage ( repoName , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
dockerCmd ( c , "push" , repoName )
dockerCmd ( c , "rmi" , repoName )
dockerfile = `
FROM busybox
COPY -- from = % s bar baz `
ctx = fakeContext ( c , fmt . Sprintf ( dockerfile , repoName ) , map [ string ] string {
"Dockerfile" : dockerfile ,
} )
defer ctx . Close ( )
result = buildImage ( "build1" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
dockerCmdWithResult ( "run" , "build1" , "cat" , "baz" ) . Assert ( c , icmd . Expected { Out : "abc" } )
}
func ( s * DockerSuite ) TestBuildFromPreviousBlock ( c * check . C ) {
dockerfile := `
FROM busybox as foo
COPY foo /
FROM foo as foo1
RUN echo 1 >> foo
FROM foo as foO2
RUN echo 2 >> foo
FROM foo
COPY -- from = foo1 foo f1
COPY -- from = FOo2 foo f2
` // foo2 case also tests that names are canse insensitive
ctx := fakeContext ( c , dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
"foo" : "bar" ,
} )
defer ctx . Close ( )
result := buildImage ( "build1" , withExternalBuildContext ( ctx ) )
result . Assert ( c , icmd . Success )
dockerCmdWithResult ( "run" , "build1" , "cat" , "foo" ) . Assert ( c , icmd . Expected { Out : "bar" } )
dockerCmdWithResult ( "run" , "build1" , "cat" , "f1" ) . Assert ( c , icmd . Expected { Out : "bar1" } )
dockerCmdWithResult ( "run" , "build1" , "cat" , "f2" ) . Assert ( c , icmd . Expected { Out : "bar2" } )
}
2017-04-04 16:54:21 +00:00
func ( s * DockerTrustSuite ) TestCopyFromTrustedBuild ( c * check . C ) {
img1 := s . setupTrustedImage ( c , "trusted-build1" )
img2 := s . setupTrustedImage ( c , "trusted-build2" )
dockerFile := fmt . Sprintf ( `
FROM % s AS build - base
RUN echo ok > / foo
FROM % s
COPY -- from = build - base foo bar ` , img1 , img2 )
name := "testcopyfromtrustedbuild"
r := buildImage ( name , trustedBuild , build . WithDockerfile ( dockerFile ) )
r . Assert ( c , icmd . Expected {
Out : fmt . Sprintf ( "FROM %s@sha" , img1 [ : len ( img1 ) - 7 ] ) ,
} )
r . Assert ( c , icmd . Expected {
Out : fmt . Sprintf ( "FROM %s@sha" , img2 [ : len ( img2 ) - 7 ] ) ,
} )
dockerCmdWithResult ( "run" , name , "cat" , "bar" ) . Assert ( c , icmd . Expected { Out : "ok" } )
}
2016-11-09 21:07:56 +00:00
// TestBuildOpaqueDirectory tests that a build succeeds which
// creates opaque directories.
// See https://github.com/docker/docker/issues/25244
func ( s * DockerSuite ) TestBuildOpaqueDirectory ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
dockerFile := `
FROM busybox
RUN mkdir / dir1 && touch / dir1 / f1
RUN rm - rf / dir1 && mkdir / dir1 && touch / dir1 / f2
RUN touch / dir1 / f3
RUN [ - f / dir1 / f2 ]
`
// Test that build succeeds, last command fails if opaque directory
// was not handled correctly
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , "testopaquedirectory" , build . WithDockerfile ( dockerFile ) )
2016-11-09 21:07:56 +00:00
}
2016-11-14 22:01:16 +00:00
// Windows test for USER in dockerfile
func ( s * DockerSuite ) TestBuildWindowsUser ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
name := "testbuildwindowsuser"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM ` + testEnv . MinimalBaseImage ( ) + `
2016-11-14 22:01:16 +00:00
RUN net user user / add
USER user
RUN set username
2017-01-10 18:16:25 +00:00
` ) ) . Assert ( c , icmd . Expected {
Out : "USERNAME=user" ,
} )
2016-11-14 22:01:16 +00:00
}
2016-11-16 23:02:27 +00:00
// Verifies if COPY file . when WORKDIR is set to a non-existing directory,
// the directory is created and the file is copied into the directory,
// as opposed to the file being copied as a file with the name of the
// directory. Fix for 27545 (found on Windows, but regression good for Linux too).
// Note 27545 was reverted in 28505, but a new fix was added subsequently in 28514.
func ( s * DockerSuite ) TestBuildCopyFileDotWithWorkdir ( c * check . C ) {
name := "testbuildcopyfiledotwithworkdir"
2017-01-10 18:16:25 +00:00
buildImageSuccessfully ( c , name , withBuildContext ( c ,
withFile ( "Dockerfile" , ` FROM busybox
WORKDIR / foo
COPY file .
RUN [ "cat" , "/foo/file" ]
` ) ,
withFile ( "file" , "content" ) ,
) )
2016-11-16 23:02:27 +00:00
}
2016-11-22 19:26:02 +00:00
// Case-insensitive environment variables on Windows
func ( s * DockerSuite ) TestBuildWindowsEnvCaseInsensitive ( c * check . C ) {
testRequires ( c , DaemonIsWindows )
name := "testbuildwindowsenvcaseinsensitive"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( `
2017-01-13 16:23:28 +00:00
FROM ` +testEnv.MinimalBaseImage()+ `
2017-01-10 18:16:25 +00:00
ENV FOO = bar foo = baz
` ) )
2016-11-22 19:26:02 +00:00
res := inspectFieldJSON ( c , name , "Config.Env" )
2017-01-10 18:16:25 +00:00
if res != ` ["foo=baz"] ` { // Should not have FOO=bar in it - takes the last one processed. And only one entry as deduped.
2016-11-22 19:26:02 +00:00
c . Fatalf ( "Case insensitive environment variables on Windows failed. Got %s" , res )
}
}
2016-12-23 19:16:15 +00:00
// Test case for 29667
func ( s * DockerSuite ) TestBuildWorkdirImageCmd ( c * check . C ) {
image := "testworkdirimagecmd"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , image , build . WithDockerfile ( `
2016-12-23 19:16:15 +00:00
FROM busybox
WORKDIR / foo / bar
2017-01-10 18:16:25 +00:00
` ) )
out , _ := dockerCmd ( c , "inspect" , "--format" , "{{ json .Config.Cmd }}" , image )
2017-01-04 23:33:40 +00:00
// The Windows busybox image has a blank `cmd`
lookingFor := ` ["sh"] `
2017-01-13 16:23:28 +00:00
if testEnv . DaemonPlatform ( ) == "windows" {
2017-01-04 23:33:40 +00:00
lookingFor = "null"
}
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , lookingFor )
2016-12-23 19:16:15 +00:00
image = "testworkdirlabelimagecmd"
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , image , build . WithDockerfile ( `
2016-12-23 19:16:15 +00:00
FROM busybox
WORKDIR / foo / bar
LABEL a = b
2017-01-10 18:16:25 +00:00
` ) )
2016-12-23 19:16:15 +00:00
out , _ = dockerCmd ( c , "inspect" , "--format" , "{{ json .Config.Cmd }}" , image )
2017-01-04 23:33:40 +00:00
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , lookingFor )
2016-12-23 19:16:15 +00:00
}
2017-01-02 18:13:26 +00:00
// Test case for 28902/28909
2016-12-23 19:16:15 +00:00
func ( s * DockerSuite ) TestBuildWorkdirCmd ( c * check . C ) {
testRequires ( c , DaemonIsLinux )
2017-01-10 18:16:25 +00:00
name := "testbuildworkdircmd"
2016-12-23 19:16:15 +00:00
dockerFile := `
2017-01-02 18:13:26 +00:00
FROM busybox
2016-12-23 19:16:15 +00:00
WORKDIR /
`
2017-03-23 17:35:22 +00:00
buildImageSuccessfully ( c , name , build . WithDockerfile ( dockerFile ) )
result := buildImage ( name , build . WithDockerfile ( dockerFile ) )
2017-01-10 18:16:25 +00:00
result . Assert ( c , icmd . Success )
c . Assert ( strings . Count ( result . Combined ( ) , "Using cache" ) , checker . Equals , 1 )
2016-12-23 19:16:15 +00:00
}
2017-01-10 23:36:08 +00:00
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) should be a unit test
2017-01-10 23:36:08 +00:00
func ( s * DockerSuite ) TestBuildLineErrorOnBuild ( c * check . C ) {
name := "test_build_line_error_onbuild"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 23:36:08 +00:00
ONBUILD
2017-01-10 18:16:25 +00:00
` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "Dockerfile parse error line 2: ONBUILD requires at least one argument" ,
} )
2017-01-10 23:36:08 +00:00
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) should be a unit test
2017-01-10 23:36:08 +00:00
func ( s * DockerSuite ) TestBuildLineErrorUknownInstruction ( c * check . C ) {
name := "test_build_line_error_unknown_instruction"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 23:36:08 +00:00
RUN echo hello world
NOINSTRUCTION echo ba
RUN echo hello
ERROR
2017-01-10 18:16:25 +00:00
` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "Dockerfile parse error line 3: Unknown instruction: NOINSTRUCTION" ,
} )
2017-01-10 23:36:08 +00:00
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) should be a unit test
2017-01-10 23:36:08 +00:00
func ( s * DockerSuite ) TestBuildLineErrorWithEmptyLines ( c * check . C ) {
name := "test_build_line_error_with_empty_lines"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( `
2017-01-10 23:36:08 +00:00
FROM busybox
RUN echo hello world
NOINSTRUCTION echo ba
CMD [ "/bin/init" ]
2017-01-10 18:16:25 +00:00
` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "Dockerfile parse error line 6: Unknown instruction: NOINSTRUCTION" ,
} )
2017-01-10 23:36:08 +00:00
}
2017-01-10 18:16:25 +00:00
// FIXME(vdemeester) should be a unit test
2017-01-10 23:36:08 +00:00
func ( s * DockerSuite ) TestBuildLineErrorWithComments ( c * check . C ) {
name := "test_build_line_error_with_comments"
2017-03-23 17:35:22 +00:00
buildImage ( name , build . WithDockerfile ( ` FROM busybox
2017-01-10 23:36:08 +00:00
# This will print hello world
# and then ba
RUN echo hello world
2017-01-10 18:16:25 +00:00
NOINSTRUCTION echo ba
` ) ) . Assert ( c , icmd . Expected {
ExitCode : 1 ,
Err : "Dockerfile parse error line 5: Unknown instruction: NOINSTRUCTION" ,
} )
2017-01-10 23:36:08 +00:00
}
2017-03-30 20:29:21 +00:00
// #31957
func ( s * DockerSuite ) TestBuildSetCommandWithDefinedShell ( c * check . C ) {
buildImageSuccessfully ( c , "build1" , build . WithDockerfile ( `
FROM busybox
SHELL [ "/bin/sh" , "-c" ]
` ) )
buildImageSuccessfully ( c , "build2" , build . WithDockerfile ( `
FROM build1
CMD echo foo
` ) )
out , _ := dockerCmd ( c , "inspect" , "--format" , "{{ json .Config.Cmd }}" , "build2" )
c . Assert ( strings . TrimSpace ( out ) , checker . Equals , ` ["/bin/sh","-c","echo foo"] ` )
}