Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
Updated the container docs to include more details (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudnautique committed Jul 7, 2022
1 parent 8d24427 commit 2fa2f36
Showing 1 changed file with 213 additions and 34 deletions.
247 changes: 213 additions & 34 deletions docs/docs/39-Acornfile/03-containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,86 @@ The container definition in the Acorn file defines everything about the individu
containers:{
"my-webapp": {
image: "nginx"
expose: "80/http"
env: {
"NGINX_HOST": "example.com"
}
}
```

## Defining a container built from a Dockerfile

### Standard build options

Acorn provides a mechanism to build your own containers for your application. If you have an existing project that already defines an Dockerfile, you can build it from Acorn.

```cue
containers: {
"my-app": {
build: {
context: "."
}
}
}
```

The above file defines a container that will be deployed named "my-webapp" and it will expose port 80 to the cluster it is running on, and publicly if needed at runtime. There is also an environment variable `NGINX_HOST` being set to `example.com`.
Now when an `acorn build .` or `acorn dev .` is run, the `my-app` container will be built and packaged as a part of the Acorn. It will look for a Dockerfile in the `./` directory.

If the application exposes more then one port, the expose field can be a list like so:
### Customized build behavior

Acorn provides options to customize the building of OCI images. If the Dockerfile is not in the root directory of the `context` you can specify the location using the `dockerfile` parameter. If the image is a multi-stage build, the desired target can be specified. See [args and profiles](/acornfile/args-and-profiles) to see how to customize these values at build and run time.

```cue
containers:{
containers: {
"my-app": {
build: {
context: "."
dockerfile: "./pkg/Dockerfile.prod"
target: "dev"
}
}
}
```

You can also specify a `buildArgs` struct as part of the build section to pass arguments to the build.

```cue
containters: {
app: {
build: {
...
buildArgs: {
param: "value"
...
}
}
}
}
```

## Network ports

Most containers can be interacted with over the network. In order for containers to be reached by other containers and applications, the network ports must be defined as part of the container.

There are two scopes when defining ports in the container struct `ports` and `expose`. The `ports` setting is for services that are meant to only be reached from other containers and jobs within the Acorn app.

```cue
containers: {
"my-webapp": {
image: "nginx"
expose: [
"80/http",
"443/tcp",
ports: [
"5000/http",
]
env: {
"NGINX_HOST": "example.com"
}
}
}
```

The above example defines a port `5000` that exposes an HTTP service. This port will not be eligible to publish out to the world.

The next example shows the `expose` parameter, used to define ports that are meant to be accessed outside of the Acorn app or published outside the cluster.

```cue
containers:{
containers: {
"my-webapp": {
image: "nginx"
expose: [
"80/http",
"443/tcp",
]
env: {
"NGINX_HOST": "example.com"
}
expose: "8080/http"
}
database: {
image: "mysql"
Expand All @@ -56,39 +98,176 @@ containers:{
}
```

This Acorn file defines two containers, one called `my-webapp` and the other `database`. In the database container, we are using the `ports` key. This means that only other containers running in this Acorn, in this case `my-webapp` can access the port.
This Acorn file defines two containers, one called `my-webapp` and the other `database`. The `my-webapp` container is exposing port 8080. When launching this Acorn the port can be published outside the cluster or accessed by linked Acorns.

Also, in the above examples there is an environment variable being defined to
In the database container, we are using the `ports` parameter because only the my-webapp container will communicate with the database.

## Defining a container from a Dockerfile
## Environment variables

Acorn provides a mechanism to build your own containers for your application. If you have an existing project that already defines an Dockerfile, you can build it from Acorn.
Containers often use environment variables as a way to configure common settings or pass in secrets. Acorn supports both methods in the container definition.

```cue
containers: {
"my-app": {
build: {
context: "."
db: {
image: "mysql"
...
env: {
"MYSQL_ROOT_PASSWORD": "secret://root-pass/token"
"DATABASE_NAME": "test-app"
"USER_SET_VALUE": args.userValue
}
expose: "3000/http"
}
}
```

Now when an `acorn build .` or `acorn dev .` is run, the `my-app` container will be built and packaged as a part of the Acorn. It will look for a Dockerfile in the `./` directory. You can specify a different file or location with the dockerfile key.
The above example has a `db` container with the `MYSQL_ROOT_PASSWORD` variable set by a [secret](/acornfile/secrets) in the Acorn file. The `DATABASE_NAME` is set to a static value, and the `USER_SET_VALUE` is defined by a user [arg](/acornfile/args-and-profiles). When launched the container can access these environment variables as needed.

## Files

Files are defined in a container where the key is the location inside the container, and the value is the contents of the file.

```cue
containers: {
"my-app": {
build: {
context: "."
dockerfile: "./pkg/Dockerfile.prod"
web: {
image: "nginx"
...
files: {
"/etc/htpasswd": "secret://htpasswd-file/content"
"/usr/share/nginx/html/index.html": "<h1>Hello!</h1>"
}
...
}
}
```

In the above, the file `/etc/htpasswd` will contain the contents from a secret that contains the appropriate values for an htpasswd file. The `/usr/share/nginx/html/index.html` will contain static content from the string.

## Directories

Directories are defined in their own block and are used to mount volumes, files from a secret, or
pull in content at build time. The block has keys that are path names inside the container and values are the source.

```cue
containers: {
web: {
image: "nginx"
...
dirs:{
"/init-scripts": "./scripts"
"/home/.ssh/": "secret://ssh-keys"
"/data": "volume://data-vol"
}
expose: "3000/http"
...
}
}
```

In the above file, when building the acorn the `/init-scripts` directory will be populated with the contents of the local `./scripts` directory. Files are copied in with the same permissions.

The `/home/.ssh/` directory will have files named after the secrets keys and content. The `/data` directory will have the volume `data-vol` mounted.

## Probes

Applications running for a long time sometimes fail in strange ways, or take time to startup before they are ready to take traffic. To ensure the container is running and ready to take traffic there are probes.

There are three types of probes readiness, liveness, and startup. Probes are defined per container in a list. You can define one of each type per container. If the probes fail, the container is restarted.

Each probe type has the following parameters that can be optionally set.

* `intialDelaySeconds`: Number of seconds to wait after the container is started before probes are initiated. The default is 0 seconds.
* `periodSeconds`: Number of seconds between probe attempts. Default is 10.
* `timeoutSeconds`: Number of seconds before the probe times out. Default is 1.
* `successThreshold`: Number of consecutive successful probes before considering the container healthy. Default is 1.
* `failureThreshold`: Number of consecutive failed probes before considering the container unhealthy. Default is 3.

There are three types of probes that can be used to check the health of the container. A script can be executed inside the container, an HTTP endpoint can be checked, or a TCP endpoint can be checked. Each of the probe types can use one of any of these check types.

### Liveness probes

The liveness probe detects that the container is up and considered running. The example here defines an HTTP type of check, though TCP and exec types could also be used.

```cue
containers: {
web: {
image: "nginx"
...
probes: [
{
type: "liveness"
http: {
url: "http://localhost/healthz"
headers: {
Accept: "application/json"
}
}
},
]
}
}
```

Headers are an optional field on the HTTP health probe type.

### Readiness probes

A readiness probe means the container is ready to take traffic. Sometimes when a database server starts it needs to have data loaded. During this data loading process, it should not be contacted by the application incase it has incomplete data. You can use this probe to prevent other containers from accessing this container.

This example will use an exec check, but HTTP and TCP checks could also be used.

*Note: Readiness probes do not wait for the liveness probe to succeed first. If you need the readiness probe to wait you should use the `initialDelaySeconds` parameter to delay. Or, the startup probe can also be used.*

```cue
containers: {
db: {
image: "mysql"
...
probes: [
{
type: "readiness"
initialDelaySeconds: 10
exec: command: [
"mysqladmin",
"status",
"-uroot",
"-p${MYSQL_ROOT_PASSWORD}",
]
},
]
}
}
```

### Startup probes

Startup probes are to allow slow starting applications time to load data and/or configuration before starting the liveness and readiness probes. The startup probe should use the same command, HTTP, or TCP check as the liveness probe with enough time to cover the worst case startup scenario. The time is calculated by `failureThreshold * periodSeconds`.

```cue
containers: {
web: {
image: "nginx"
...
probes: [
{
type: "liveness"
tcp:{
url: tcp://localhost:80
}
},
{
"type: "startup"
failureThreshold: 10
periodSeconds: 6
tcp:{
url: tcp://localhost:80
}
}
]
}
}
```

In the above example the `web` container would have 60 seconds (6s * 10) to startup before being restarted.

## Defining sidecar containers

Sometimes a container needs some setup before it runs, or has additional services running along side it. For these scenarios, the `sidecar` can be defined as part of the container.
Expand Down

0 comments on commit 2fa2f36

Please sign in to comment.