Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build docker images when building packages #8898

Merged
merged 30 commits into from
Nov 13, 2018
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c9ab6a4
Include docker image building in package release build
jsoriano Nov 1, 2018
cb332ea
Reorganize code, save docker as artifact, parametrize vendor
jsoriano Nov 3, 2018
4e07f55
Reuse data for templates
jsoriano Nov 3, 2018
fde2cf5
Fix permissions
jsoriano Nov 3, 2018
c42dc23
Better parametrize urls in Dockerfile
jsoriano Nov 4, 2018
ece0946
Use helper function for version
jsoriano Nov 4, 2018
c614a80
Set docker from and user from spec file
jsoriano Nov 4, 2018
c743ba8
Set linux capabilities on heartbeat and packetbeat
jsoriano Nov 4, 2018
691bf7b
Build docker for filebeat
jsoriano Nov 4, 2018
530bc94
Use beat name as default user name in docker
jsoriano Nov 5, 2018
c72feaf
Don't rely on current directory for files chmods
jsoriano Nov 5, 2018
ae4239a
Use proper license variable in Dockerfile
jsoriano Nov 5, 2018
1900d1f
Set capabilities after setting owner and permissions
jsoriano Nov 5, 2018
b15df4e
Add all kibana.generated directories to gitignore
jsoriano Nov 5, 2018
d72283c
Add specific configuration for docker images
jsoriano Nov 5, 2018
068f011
Parametrize base docker repository
jsoriano Nov 5, 2018
a0568cd
Remove unused Env
jsoriano Nov 6, 2018
67daa1a
Precalculate build and beat directories
jsoriano Nov 6, 2018
c8b015d
Add comment
jsoriano Nov 6, 2018
98c8f9b
Reorder commands in dockerfile so less layers are created
jsoriano Nov 6, 2018
7d6a294
Added changelog entry
jsoriano Nov 6, 2018
51ef1f6
Generate docker config for custom beats
jsoriano Nov 6, 2018
a30833c
Merge remote-tracking branch 'origin/master' into mage-package-docker
jsoriano Nov 6, 2018
e5ca02c
Add commit sha to docker labels
jsoriano Nov 6, 2018
e449166
Add some tests for docker packaging
jsoriano Nov 6, 2018
85ef192
Add expose_ports extra var to expose ports in dockers
jsoriano Nov 8, 2018
8e6a323
Set repository only for elastic dockers
jsoriano Nov 8, 2018
2b4b1af
Merge remote-tracking branch 'origin/master' into mage-package-docker
jsoriano Nov 13, 2018
db3987d
Revert "Add all kibana.generated directories to gitignore"
jsoriano Nov 13, 2018
39f1bc2
Fail if docker entry point is not an absolute path
jsoriano Nov 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/*/fields.yml
/*/*.template*.json
**/html_docs
/*/_meta/kibana.generated
/**/_meta/kibana.generated
jsoriano marked this conversation as resolved.
Show resolved Hide resolved

# Files
.DS_Store
Expand Down
14 changes: 14 additions & 0 deletions auditbeat/_meta/beat.docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
auditbeat.modules:

- module: auditd
audit_rules: |
-w /etc/passwd -p wa -k identity
-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -k access

- module: file_integrity
paths:
- /bin
- /usr/bin
- /sbin
- /usr/sbin
- /etc
21 changes: 21 additions & 0 deletions auditbeat/auditbeat.docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
auditbeat.modules:

- module: auditd
audit_rules: |
-w /etc/passwd -p wa -k identity
-a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -k access

- module: file_integrity
paths:
- /bin
- /usr/bin
- /sbin
- /usr/sbin
- /etc
processors:
- add_cloud_metadata: ~

output.elasticsearch:
hosts: '${ELASTICSEARCH_HOSTS:elasticsearch:9200}'
username: '${ELASTICSEARCH_USERNAME:}'
password: '${ELASTICSEARCH_PASSWORD:}'
2 changes: 2 additions & 0 deletions auditbeat/magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ func customizePackaging() {
case mage.Deb, mage.RPM, mage.DMG:
args.Spec.ReplaceFile("/etc/{{.BeatName}}/{{.BeatName}}.yml", shortConfig)
args.Spec.ReplaceFile("/etc/{{.BeatName}}/{{.BeatName}}.reference.yml", referenceConfig)
case mage.Docker:
args.Spec.ExtraVar("user", "root")
default:
panic(errors.Errorf("unhandled package type: %v", pkgType))
}
Expand Down
143 changes: 143 additions & 0 deletions dev-tools/mage/dockerbuilder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package mage

import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/magefile/mage/sh"

jsoriano marked this conversation as resolved.
Show resolved Hide resolved
"github.com/pkg/errors"
)

type dockerBuilder struct {
PackageSpec

buildDir string
beatDir string
}

func newDockerBuilder(spec PackageSpec) (*dockerBuilder, error) {
buildDir := filepath.Join(spec.packageDir, "docker-build")
beatDir := filepath.Join(buildDir, "beat")

return &dockerBuilder{
PackageSpec: spec,
buildDir: buildDir,
beatDir: beatDir,
}, nil
}

func (b *dockerBuilder) Build() error {
if err := os.RemoveAll(b.buildDir); err != nil {
return errors.Wrapf(err, "failed to clean existing build directory %s", b.buildDir)
}

if err := b.copyFiles(); err != nil {
return err
}

if err := b.prepareBuild(); err != nil {
return errors.Wrap(err, "failed to prepare build")
}

tag, err := b.dockerBuild()
if err != nil {
return errors.Wrap(err, "failed to build docker")
}

if err := b.dockerSave(tag); err != nil {
return errors.Wrap(err, "failed to save docker as artifact")
}

return nil
}

func (b *dockerBuilder) modulesDirs() []string {
var modulesd []string
for _, f := range b.Files {
if f.Modules {
modulesd = append(modulesd, f.Target)
}
}
return modulesd
}

func (b *dockerBuilder) copyFiles() error {
for _, f := range b.Files {
target := filepath.Join(b.beatDir, f.Target)
if err := Copy(f.Source, target); err != nil {
return errors.Wrapf(err, "failed to copy from %s to %s", f.Source, target)
}
}
return nil
}

func (b *dockerBuilder) prepareBuild() error {
elasticBeatsDir, err := ElasticBeatsDir()
if err != nil {
return err
}
templatesDir := filepath.Join(elasticBeatsDir, "dev-tools/packaging/templates/docker")

data := map[string]interface{}{
"ModulesDirs": b.modulesDirs(),
}

return filepath.Walk(templatesDir, func(path string, info os.FileInfo, _ error) error {
if !info.IsDir() {
target := strings.TrimSuffix(
filepath.Join(b.buildDir, filepath.Base(path)),
".tmpl",
)

err = b.ExpandFile(path, target, data)
if err != nil {
return errors.Wrapf(err, "expanding template '%s' to '%s'", path, target)
}
}
return nil
})
}

func (b *dockerBuilder) dockerBuild() (string, error) {
tag := fmt.Sprintf("%s:%s", b.Name, b.Version)
if repository, _ := b.ExtraVars["repository"]; repository != "" {
tag = fmt.Sprintf("%s/%s", repository, tag)
}
return tag, sh.Run("docker", "build", "-t", tag, b.buildDir)
}

func (b *dockerBuilder) dockerSave(tag string) error {
// Save the container as artifact
outputFile := b.OutputFile
if outputFile == "" {
outputTar, err := b.Expand(defaultBinaryName + ".docker.tar")
if err != nil {
return err
}
outputFile = filepath.Join(distributionsDir, outputTar)
}
if err := sh.Run("docker", "save", "-o", outputFile, tag); err != nil {
graphaelli marked this conversation as resolved.
Show resolved Hide resolved
return err
}
return errors.Wrap(CreateSHA512File(outputFile), "failed to create .sha512 file")
}
32 changes: 32 additions & 0 deletions dev-tools/mage/pkgtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const (
Zip
TarGz
DMG
Docker
)

// OSPackageArgs define a set of package types to build for an operating
Expand Down Expand Up @@ -103,6 +104,7 @@ type PackageFile struct {
Target string `yaml:"target,omitempty"` // Target location in package. Relative paths are added to a package specific directory (e.g. metricbeat-7.0.0-linux-x86_64).
Mode os.FileMode `yaml:"mode,omitempty"` // Target mode for file. Does not apply when source is a directory.
Config bool `yaml:"config"` // Mark file as config in the package (deb and rpm only).
Modules bool `yaml:"modules"` // Mark directory as directory with modules.
Dep func(PackageSpec) error `yaml:"-" hash:"-" json:"-"` // Dependency to invoke during Evaluate.
}

Expand Down Expand Up @@ -165,6 +167,9 @@ var OSArchNames = map[string]map[PackageType]map[string]string{
"ppc64le": "ppc64le",
"s390x": "s390x",
},
Docker: map[string]string{
"amd64": "amd64",
},
},
}

Expand Down Expand Up @@ -204,6 +209,8 @@ func (typ PackageType) String() string {
return "tar.gz"
case DMG:
return "dmg"
case Docker:
return "docker"
default:
return "invalid"
}
Expand All @@ -227,6 +234,8 @@ func (typ *PackageType) UnmarshalText(text []byte) error {
*typ = Zip
case "dmg":
*typ = DMG
case "docker":
*typ = Docker
default:
return errors.Errorf("unknown package type: %v", string(text))
}
Expand Down Expand Up @@ -256,6 +265,8 @@ func (typ PackageType) Build(spec PackageSpec) error {
return PackageTarGz(spec)
case DMG:
return PackageDMG(spec)
case Docker:
return PackageDocker(spec)
default:
return errors.Errorf("unknown package type: %v", typ)
}
Expand All @@ -282,6 +293,14 @@ func (s PackageSpec) ReplaceFile(target string, file PackageFile) {
s.Files[target] = file
}

// ExtraVar adds or replaces a variable to `extra_vars` in package specs.
func (s *PackageSpec) ExtraVar(key, value string) {
jsoriano marked this conversation as resolved.
Show resolved Hide resolved
if s.ExtraVars == nil {
s.ExtraVars = make(map[string]string)
}
s.ExtraVars[key] = value
}

// Expand expands a templated string using data from the spec.
func (s PackageSpec) Expand(in string, args ...map[string]interface{}) (string, error) {
return expandTemplate("inline", in, FuncMap,
Expand Down Expand Up @@ -823,3 +842,16 @@ func PackageDMG(spec PackageSpec) error {

return b.Build()
}

// PackageDocker packages the Beat into a docker image.
func PackageDocker(spec PackageSpec) error {
if err := HaveDocker(); err != nil {
return errors.Errorf("docker daemon required to build images: %s", err)
}

b, err := newDockerBuilder(spec)
if err != nil {
return err
}
return b.Build()
}
47 changes: 47 additions & 0 deletions dev-tools/packaging/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,19 @@ shared:
template: '{{ elastic_beats_dir }}/dev-tools/packaging/templates/windows/uninstall-service.ps1.tmpl'
mode: 0755

- &docker_spec
<<: *binary_spec
extra_vars:
from: 'centos:7'
user: '{{ .BeatName }}'
repository: 'docker.elastic.co/beats'
graphaelli marked this conversation as resolved.
Show resolved Hide resolved
linux_capabilities: ''
jsoriano marked this conversation as resolved.
Show resolved Hide resolved
files:
'{{.BeatName}}.yml':
source: '{{.BeatName}}.docker.yml'
mode: 0600
config: true

#
# License modifiers for Apache 2.0
#
Expand Down Expand Up @@ -229,6 +242,11 @@ specs:
spec:
<<: *deb_rpm_spec

- os: linux
types: [docker]
spec:
<<: *docker_spec

elastic_beat_without_xpack:
###
# OSS Packages
Expand Down Expand Up @@ -268,6 +286,13 @@ specs:
<<: *apache_license_for_deb_rpm
name: '{{.BeatName}}-oss'

- os: linux
types: [docker]
spec:
<<: *docker_spec
<<: *apache_license_for_binaries
name: '{{.BeatName}}-oss'

###
# Elastic Licensed Packages
###
Expand Down Expand Up @@ -301,6 +326,12 @@ specs:
<<: *deb_rpm_spec
<<: *elastic_license_for_deb_rpm

- os: linux
types: [docker]
spec:
<<: *docker_spec
<<: *elastic_license_for_binaries

# Official Beats
elastic_beat:
###
Expand Down Expand Up @@ -341,6 +372,13 @@ specs:
<<: *apache_license_for_deb_rpm
name: '{{.BeatName}}-oss'

- os: linux
types: [docker]
spec:
<<: *docker_spec
<<: *apache_license_for_binaries
name: '{{.BeatName}}-oss'

###
# Elastic Licensed Packages
###
Expand Down Expand Up @@ -385,3 +423,12 @@ specs:
files:
/usr/share/{{.BeatName}}/bin/{{.BeatName}}{{.BinaryExt}}:
source: ../x-pack/{{.BeatName}}/build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}}

- os: linux
types: [docker]
spec:
<<: *docker_spec
<<: *elastic_license_for_binaries
files:
'{{.BeatName}}{{.BinaryExt}}':
source: ../x-pack/{{.BeatName}}/build/golang-crossbuild/{{.BeatName}}-{{.GOOS}}-{{.Platform.Arch}}{{.BinaryExt}}
Loading