Skip to content

Commit

Permalink
Rephrase "image tag" to "image name". (#62)
Browse files Browse the repository at this point in the history
Docker naming is a bit confusing. There's, repos, images, tags, image
ids, and image digests.

- `docker tag` takes a tag, right? No. It takes an image name and
  optionally a tag (see `man docker tag`). Though, the image name can be
  prefixed with a repository.
- What about `docker build --tag`. That surely takes a tag? Again no.
  It's like `docker tag`. It takes an image name with an optional repo
  prefix and optional tag suffix.
- `docker images` shows `REPOSITORY` and `TAG`, though the thing under
  `REPOSITORY` may not have a repository at all.

This PR tries to clarify some wording around docker by renaming some
places we say "tag" to say "image" instead. It also updates some stale
documentation.
  • Loading branch information
mwhittaker authored Oct 5, 2023
1 parent bdb7034 commit 96b680b
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 68 deletions.
48 changes: 22 additions & 26 deletions cmd/weaver-kube/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,40 +43,36 @@ var (
Name: "deploy",
Description: "Deploy a Service Weaver app",
Help: `Usage:
weaver kube deploy <configfile>
weaver kube deploy <config file>
Flags:
-h, --help Print this help message.
Container Image Names:
"weaver kube deploy" builds a container image locally, and optionally uploads
it to a container repository. The repository can be specified using the
"repo" field inside the "kube" section of the config file. For example,
consider the following config file:
it to a container repository. The name of the image and the repository to
which the image is uploaded are specified using the "image" and "repo" fields
inside the "kube" section of the config file. For example, consider the
following config file:
[serviceweaver]
binary = "./foo"
[kube]
tag = "foo/foo:0.0.1"
repo = "docker.io/my_docker_hub_username/my_repo"
Using this config file, "weaver kube deploy" will build a container
with a local build tag [1] "foo/foo:0.0.1", and upload it to the
"docker.io/my_docker_hub_username/my_repo" repository. If the "tag" is not
specified, it defaults to "<app_name>:<app_version>. If the "repo"
is not specified, the container is not uploaded and must be pushed
manually to the Kubernetes environments.
image = "foo:0.0.1"
repo = "docker.io/my_docker_hub_username"
Using this config file, "weaver kube deploy" will build an image named
"foo:0.0.1" and upload it to "docker.io/my_docker_hub_username/foo:0.0.1". If
the "image" field is not specified, the image name defaults to
"<app_name>:<app_version>". If the "repo" field is not specified, the
container is not uploaded.
Example repositories are:
- Docker Hub: docker.io/USERNAME/REPO_NAME
- Google Artifact Registry: LOCATION-docker.pkg.dev/PROJECT-ID/REPO_NAME
- GitHub Container Registry: ghcr.io/NAMESPACE
Note that the final image tag for the application container will
be a concatenation of repo and tag fields, i.e., "repo/tag".
[1]: https://docs.docker.com/engine/reference/commandline/tag/`,
- Docker Hub: docker.io/USERNAME
- Google Artifact Registry: LOCATION-docker.pkg.dev/PROJECT-ID
- GitHub Container Registry: ghcr.io/NAMESPACE`,
Flags: flags,
Fn: deploy,
}
Expand Down Expand Up @@ -144,7 +140,7 @@ func deploy(ctx context.Context, args []string) error {
}

// Build the docker image for the deployment.
image, err := impl.BuildAndUploadDockerImage(ctx, dep, config.LocalTag, config.Repo)
image, err := impl.BuildAndUploadDockerImage(ctx, dep, config.Image, config.Repo)
if err != nil {
return err
}
Expand Down Expand Up @@ -183,13 +179,13 @@ func checkVersionCompatibility(appBinary string) error {
github.com/ServiceWeaver/weaver module version %s. However, the 'weaver-kube'
binary you're using was built with weaver module version %s. These versions are
incompatible.
We recommend updating both the weaver module your application is built with and
updating the 'weaver-kube' command by running the following.
go get github.com/ServiceWeaver/weaver@latest
go install github.com/ServiceWeaver/weaver-kube/cmd/weaver-kube@latest
Then, re-build your code and re-run 'weaver-kube deploy'. If the problem
persists, please file an issue at https://github.com/ServiceWeaver/weaver/issues`,
relativize(appBinary), versions.ModuleVersion, selfVersion)
Expand Down
48 changes: 24 additions & 24 deletions internal/impl/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ ENTRYPOINT ["/weaver/weaver-kube"]

// buildSpec holds information about a container image build.
type buildSpec struct {
tag string // tag is the container build tag
image string // container image name
files []string // files that should be copied to the container
goInstall []string // binary targets that should be 'go install'-ed
}

// BuildAndUploadDockerImage builds a docker image and uploads it to a remote
// repo, if one is specified. It returns the docker image tag that should
// be used in the application containers.
func BuildAndUploadDockerImage(ctx context.Context, dep *protos.Deployment, buildTag, dockerRepo string) (string, error) {
// repo, if one is specified. It returns the image name that should be used in
// Kubernetes YAML files.
func BuildAndUploadDockerImage(ctx context.Context, dep *protos.Deployment, image, repo string) (string, error) {
// Create the build specifications.
spec, err := dockerBuildSpec(dep, buildTag)
spec, err := dockerBuildSpec(dep, image)
if err != nil {
return "", fmt.Errorf("unable to build image spec: %w", err)
}
Expand All @@ -71,18 +71,18 @@ func BuildAndUploadDockerImage(ctx context.Context, dep *protos.Deployment, buil
return "", fmt.Errorf("unable to create image: %w", err)
}

tag := spec.tag
if dockerRepo != "" {
image = spec.image
if repo != "" {
// Push the docker image to the repo.
if tag, err = pushImage(ctx, tag, dockerRepo); err != nil {
if image, err = pushImage(ctx, image, repo); err != nil {
return "", fmt.Errorf("unable to push image: %w", err)
}
}
return tag, nil
return image, nil
}

// dockerBuildSpec creates a build specification for an app deployment.
func dockerBuildSpec(dep *protos.Deployment, buildTag string) (*buildSpec, error) {
func dockerBuildSpec(dep *protos.Deployment, image string) (*buildSpec, error) {
// Figure out which tool binary will run inside the container.
toolVersion, toolIsDev, err := ToolVersion()
if err != nil {
Expand Down Expand Up @@ -116,20 +116,20 @@ downloaded and installed in the container. Do you want to proceed? [Y/n] `)
toInstall = append(toInstall, "github.com/ServiceWeaver/weaver-kube/cmd/weaver-kube@"+toolVersion)
}

if buildTag == "" {
buildTag = fmt.Sprintf("%s:%s", dep.App.Name, dep.Id[:8])
if image == "" {
image = fmt.Sprintf("%s:%s", dep.App.Name, dep.Id[:8])
}

return &buildSpec{
tag: buildTag,
image: image,
files: toCopy,
goInstall: toInstall,
}, nil
}

// buildImage builds a docker image with a given spec.
func buildImage(ctx context.Context, spec *buildSpec) error {
fmt.Fprintf(os.Stderr, greenText(), fmt.Sprintf("Building image %s...", spec.tag))
fmt.Fprintf(os.Stderr, greenText(), fmt.Sprintf("Building image %s...", spec.image))
// Create:
// workDir/
// file1
Expand Down Expand Up @@ -167,24 +167,24 @@ func buildImage(ctx context.Context, spec *buildSpec) error {
if err := dockerFile.Close(); err != nil {
return err
}
return dockerBuild(ctx, workDir, spec.tag)
return dockerBuild(ctx, workDir, spec.image)
}

// dockerBuild builds a docker image given a directory and an image tag.
func dockerBuild(ctx context.Context, dir, tag string) error {
fmt.Fprintln(os.Stderr, "Building with tag:", tag)
c := exec.CommandContext(ctx, "docker", "build", dir, "-t", tag)
// dockerBuild builds a docker image given a directory and an image name.
func dockerBuild(ctx context.Context, dir, image string) error {
fmt.Fprintln(os.Stderr, "Building image ", image)
c := exec.CommandContext(ctx, "docker", "build", dir, "-t", image)
c.Stdout = os.Stderr
c.Stderr = os.Stderr
return c.Run()
}

// pushImage pushes a docker image with a given build tag to a docker
// repository, returning its tag in the repository.
func pushImage(ctx context.Context, tag, repo string) (string, error) {
// pushImage pushes the provided docker image to the provided repo, returning
// the repo-qualified image name.
func pushImage(ctx context.Context, image, repo string) (string, error) {
fmt.Fprintf(os.Stderr, greenText(), fmt.Sprintf("\nUploading image to %s...", repo))
repoTag := path.Join(repo, tag)
cTag := exec.CommandContext(ctx, "docker", "tag", tag, repoTag)
repoTag := path.Join(repo, image)
cTag := exec.CommandContext(ctx, "docker", "tag", image, repoTag)
cTag.Stdout = os.Stderr
cTag.Stderr = os.Stderr
if err := cTag.Run(); err != nil {
Expand Down
35 changes: 17 additions & 18 deletions internal/impl/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,28 +93,27 @@ type ListenerOptions struct {
// KubeConfig stores the configuration information for one execution of a
// Service Weaver application deployed using the Kube deployer.
type KubeConfig struct {
// LocalTag is the build tag for the application container on the local
// machine.
// Image is the name of the container image hosting the Service Weaver
// application.
//
// If empty, the tag defaults to "<app_name>:<app_version>", where
// <app_version> is the unique version id of the application deployment.
LocalTag string `toml:"local_tag"`

// Repo is the name of the repository the container should be uploaded to.
// For example, if set to "docker.io/alanturing/repo", "weaver kube deploy"
// will build the container locally, tag it with the appropriate Tag, and
// then push it to "docker.io/alanturing/repo".
// If empty, the image name defaults to "<app_name>:<app_version>", where
// <app_name> is the name of the app, and <app_version> is the unique
// version id of the application deployment.
Image string

// Repo is the name of the repository where the container image is uploaded.
//
// If empty, the container is built and tagged locally, but is not pushed
// to a repository.
// For example, if Image is "mycontainer:v1" and Repo is
// "docker.io/alanturing", then "weaver kube deploy" will build the image
// locally as "mycontainer:v1" and then push it to
// "docker.io/alanturing/mycontainer:v1".
//
// Example repositories are:
// - Docker Hub : docker.io/USERNAME/REPO_NAME
// - Google Artifact Registry : LOCATION-docker.pkg.dev/PROJECT-ID/REPO_NAME
// - GitHub Container Registry: ghcr.io/NAMESPACE
// If empty, the image is not pushed to a repository.
//
// Note that the final image tag for the application container will
// be a concatenation of Repo and Tag, i.e., "Repo/Tag".
// Example repositories are:
// - Docker Hub : docker.io/USERNAME
// - Google Artifact Registry : LOCATION-docker.pkg.dev/PROJECT-ID
// - GitHub Container Registry : ghcr.io/NAMESPACE
Repo string

// Namespace is the name of the Kubernetes namespace where the application
Expand Down

0 comments on commit 96b680b

Please sign in to comment.