Honor ENTRYPOINT in image

When an image has an ENTRYPOINT defined, we should be honoring it. The
problem is described in issue .

Also, added buildah binary to test runtimes for testing entrypoint and
will also allow us to test podman build as well.

Signed-off-by: baude <bbaude@redhat.com>

Closes: 
Approved by: rhatdan
This commit is contained in:
baude
2018-02-10 11:57:05 -06:00
committed by Atomic Bot
parent 773aa61f66
commit d26266659d
8 changed files with 160 additions and 12 deletions

@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y \
e2fslibs-dev \ e2fslibs-dev \
gawk \ gawk \
gettext \ gettext \
go-md2man \
iptables \ iptables \
pkg-config \ pkg-config \
libaio-dev \ libaio-dev \
@ -96,6 +97,14 @@ RUN set -x \
&& cp "$GOPATH"/bin/crictl /usr/bin/ \ && cp "$GOPATH"/bin/crictl /usr/bin/ \
&& rm -rf "$GOPATH" && rm -rf "$GOPATH"
# Install buildah
RUN set -x \
&& export GOPATH=/go \
&& git clone https://github.com/projectatomic/buildah "$GOPATH/src/github.com/projectatomic/buildah" \
&& cd "$GOPATH/src/github.com/projectatomic/buildah" \
&& make \
&& make install
# Install ginkgo # Install ginkgo
RUN set -x \ RUN set -x \
&& export GOPATH=/go \ && export GOPATH=/go \

@ -9,6 +9,7 @@ RUN yum -y install btrfs-progs-devel \
glib2-devel \ glib2-devel \
gnupg \ gnupg \
golang \ golang \
golang-github-cpuguy83-go-md2man \
gpgme-devel \ gpgme-devel \
libassuan-devel \ libassuan-devel \
libseccomp-devel \ libseccomp-devel \
@ -34,6 +35,14 @@ RUN set -x \
&& cp bin/* /usr/libexec/cni \ && cp bin/* /usr/libexec/cni \
&& rm -rf "$GOPATH" && rm -rf "$GOPATH"
# Install buildah
RUN set -x \
&& export GOPATH=/go \
&& git clone https://github.com/projectatomic/buildah "$GOPATH/src/github.com/projectatomic/buildah" \
&& cd "$GOPATH/src/github.com/projectatomic/buildah" \
&& make \
&& make install
# Install ginkgo # Install ginkgo
RUN set -x \ RUN set -x \
&& export GOPATH=/go \ && export GOPATH=/go \

@ -10,6 +10,7 @@ RUN dnf -y install btrfs-progs-devel \
glib2-devel \ glib2-devel \
gnupg \ gnupg \
golang \ golang \
golang-github-cpuguy83-go-md2man \
gpgme-devel \ gpgme-devel \
libassuan-devel \ libassuan-devel \
libseccomp-devel \ libseccomp-devel \
@ -36,6 +37,14 @@ RUN set -x \
&& cp bin/* /usr/libexec/cni \ && cp bin/* /usr/libexec/cni \
&& rm -rf "$GOPATH" && rm -rf "$GOPATH"
# Install buildah
RUN set -x \
&& export GOPATH=/go \
&& git clone https://github.com/projectatomic/buildah "$GOPATH/src/github.com/projectatomic/buildah" \
&& cd "$GOPATH/src/github.com/projectatomic/buildah" \
&& make \
&& make install
# Install ginkgo # Install ginkgo
RUN set -x \ RUN set -x \
&& export GOPATH=/go \ && export GOPATH=/go \

@ -173,7 +173,7 @@ var createFlags = []cli.Flag{
Name: "dns-search", Name: "dns-search",
Usage: "Set custom DNS search domains", Usage: "Set custom DNS search domains",
}, },
cli.StringFlag{ cli.StringSliceFlag{
Name: "entrypoint", Name: "entrypoint",
Usage: "Overwrite the default ENTRYPOINT of the image", Usage: "Overwrite the default ENTRYPOINT of the image",
}, },

@ -81,7 +81,7 @@ type createConfig struct {
DNSOpt []string //dns-opt DNSOpt []string //dns-opt
DNSSearch []string //dns-search DNSSearch []string //dns-search
DNSServers []string //dns DNSServers []string //dns
Entrypoint string //entrypoint Entrypoint []string //entrypoint
Env map[string]string //env Env map[string]string //env
ExposedPorts map[nat.Port]struct{} ExposedPorts map[nat.Port]struct{}
GroupAdd []uint32 // group-add GroupAdd []uint32 // group-add
@ -419,14 +419,14 @@ func imageData(c *cli.Context, runtime *libpod.Runtime, image string) (string, s
// Parses CLI options related to container creation into a config which can be // Parses CLI options related to container creation into a config which can be
// parsed into an OCI runtime spec // parsed into an OCI runtime spec
func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*createConfig, error) { func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*createConfig, error) {
var command []string var inputCommand, command []string
var memoryLimit, memoryReservation, memorySwap, memoryKernel int64 var memoryLimit, memoryReservation, memorySwap, memoryKernel int64
var blkioWeight uint16 var blkioWeight uint16
imageID := data.ID imageID := data.ID
if len(c.Args()) > 1 { if len(c.Args()) > 1 {
command = c.Args()[1:] inputCommand = c.Args()[1:]
} }
sysctl, err := validateSysctl(c.StringSlice("sysctl")) sysctl, err := validateSysctl(c.StringSlice("sysctl"))
@ -567,15 +567,24 @@ func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string,
workDir = data.Config.WorkingDir workDir = data.Config.WorkingDir
} }
// COMMAND // ENTRYPOINT
if len(command) == 0 { // User input entrypoint takes priority over image entrypoint
command = data.Config.Cmd entrypoint := c.StringSlice("entrypoint")
if len(entrypoint) == 0 {
entrypoint = data.Config.Entrypoint
} }
// ENTRYPOINT // Build the command
entrypoint := c.String("entrypoint") // If we have an entry point, it goes first
if entrypoint == "" { if len(entrypoint) > 0 {
entrypoint = strings.Join(data.Config.Entrypoint, " ") command = entrypoint
}
if len(inputCommand) > 0 {
// User command overrides data CMD
command = append(command, inputCommand...)
} else if len(data.Config.Cmd) > 0 && !c.IsSet("entrypoint") {
// If not user command, add CMD
command = append(command, data.Config.Cmd...)
} }
// EXPOSED PORTS // EXPOSED PORTS

@ -2,6 +2,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"strings"
specs "github.com/opencontainers/runtime-spec/specs-go" specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -223,7 +224,7 @@ func getCtrInspectInfo(ctr *libpod.Container, ctrInspectData *inspect.ContainerI
OpenStdin: config.Stdin, OpenStdin: config.Stdin,
StopSignal: config.StopSignal, StopSignal: config.StopSignal,
Cmd: config.Spec.Process.Args, Cmd: config.Spec.Process.Args,
Entrypoint: createArtifact.Entrypoint, Entrypoint: strings.Join(createArtifact.Entrypoint, " "),
}, },
} }
return data, nil return data, nil

@ -449,3 +449,14 @@ func (p *PodmanTest) GetContainerStatus() string {
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()
return session.OutputToString() return session.OutputToString()
} }
// BuildImage uses podman build and buildah to build an image
// called imageName based on a string dockerfile
func (p *PodmanTest) BuildImage(dockerfile, imageName string) {
dockerfilePath := filepath.Join(p.TempDir, "Dockerfile")
err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755)
Expect(err).To(BeNil())
session := p.Podman([]string{"build", "-t", imageName, "--file", dockerfilePath, p.TempDir})
session.Wait(120)
Expect(session.ExitCode()).To(Equal(0))
}

@ -0,0 +1,100 @@
package integration
import (
"os"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Podman run entrypoint", func() {
var (
tempdir string
err error
podmanTest PodmanTest
)
BeforeEach(func() {
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
}
podmanTest = PodmanCreate(tempdir)
podmanTest.RestoreArtifact(ALPINE)
})
AfterEach(func() {
podmanTest.Cleanup()
})
It("podman run entrypoint", func() {
dockerfile := `FROM docker.io/library/alpine:latest
ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
`
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest")
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(len(session.OutputToStringArray())).To(Equal(3))
})
It("podman run entrypoint with cmd", func() {
dockerfile := `FROM docker.io/library/alpine:latest
CMD [ "-v"]
ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
`
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest")
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(len(session.OutputToStringArray())).To(Equal(5))
})
It("podman run entrypoint with user cmd overrides image cmd", func() {
dockerfile := `FROM docker.io/library/alpine:latest
CMD [ "-v"]
ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
`
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest")
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest", "-i"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(len(session.OutputToStringArray())).To(Equal(6))
})
It("podman run entrypoint with user cmd no image cmd", func() {
dockerfile := `FROM docker.io/library/alpine:latest
ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
`
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest")
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest", "-i"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(len(session.OutputToStringArray())).To(Equal(6))
})
It("podman run user entrypoint overrides image entrypoint and image cmd", func() {
dockerfile := `FROM docker.io/library/alpine:latest
CMD ["-i"]
ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
`
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest")
session := podmanTest.Podman([]string{"run", "--entrypoint=uname", "foobar.com/entrypoint:latest"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.LineInOuputStartsWith("Linux")).To(BeTrue())
})
It("podman run user entrypoint with command overrides image entrypoint and image cmd", func() {
dockerfile := `FROM docker.io/library/alpine:latest
CMD ["-i"]
ENTRYPOINT ["grep", "Alpine", "/etc/os-release"]
`
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest")
session := podmanTest.Podman([]string{"run", "--entrypoint=uname", "foobar.com/entrypoint:latest", "-r"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.LineInOuputStartsWith("Linux")).To(BeFalse())
})
})