on your machine, but this time these Go modules will be installed into a
directory inside the image.
```dockerfile
RUN go mod download
```
At this point, you have a Go toolchain version 1.19.x and all your Go
dependencies installed inside the image.
The next thing you need to do is to copy your source code into the image. You’ll
use the `COPY` command just like you did with your module files before.
```dockerfile
COPY *.go ./
```
This `COPY` command uses a wildcard to copy all files with `.go` extension
located in the current directory on the host (the directory where the `Dockerfile`
is located) into the current directory inside the image.
Now, to compile your application, use the familiar `RUN` command:
```dockerfile
RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping
```
This should be familiar. The result of that command will be a static application
binary named `docker-gs-ping` and located in the root of the filesystem of the
image that you are building. You could have put the binary into any other place
you desire inside that image, the root directory has no special meaning in this
regard. It's just convenient to use it to keep the file paths short for improved
readability.
Now, all that is left to do is to tell Docker what command to run when your
image is used to start a container.
You do this with the `CMD` command:
```dockerfile
CMD ["/docker-gs-ping"]
```
Here's the complete `Dockerfile`:
```dockerfile
# syntax=docker/dockerfile:1
FROM golang:1.19
# Set destination for COPY
WORKDIR /app
# Download Go modules
COPY go.mod go.sum ./
RUN go mod download
# Copy the source code. Note the slash at the end, as explained in
# https://docs.docker.com/reference/dockerfile/#copy
COPY *.go ./
# Build
RUN CGO_ENABLED=0 GOOS=linux go build -o /docker-gs-ping
# Optional:
# To bind to a TCP port, runtime parameters must be supplied to the docker command.
# But we can document in the Dockerfile what ports
# the application is going to listen on by default.
# https://docs.docker.com/reference/dockerfile/#expose
EXPOSE 8080
# Run
CMD ["/docker-gs-ping"]
```
The `Dockerfile` may also contain comments. They always begin with a `#` symbol,
and must be at the beginning of a line. Comments are there for your convenience
to allow documenting your `Dockerfile`.
There is also a concept of Dockerfile directives, such as the `syntax` directive
you added. The directives must always be at the very top of the `Dockerfile`, so
when adding comments, make sure that the comments follow after any directives
that you may have used:
```dockerfile
# syntax=docker/dockerfile:1
# A sample microservice in Go packaged into a container image.
FROM golang:1.19
# ...
```
## Build the image
Now that you've created your `Dockerfile`, build an image from it. The `docker
build` command creates Docker images from the `Dockerfile` and a context. A
build context is the set of files located in the specified path or URL. The
Docker build process can access any of the files located in the context.
The build command optionally takes a `--tag` flag. This flag is used to label
the image with a string value, which is easy for humans to read and recognize.
If you don't pass a `--tag`, Docker will use `latest` as the default value.
Build your first Docker image.
```console
$ docker build --tag docker-gs-ping .
```
The build process will print some diagnostic messages as it goes through the build steps.
The following is just an example of what these messages may look like.
```console
[+] Building 2.2s (15/15) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 701B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s