Provide a way to mount common volumes to Docker containers used by Actions #378

Open
opened 2023-10-16 22:11:13 +00:00 by leedega · 3 comments

When running an action in Gitea which make use of of Docker containers for their builds, it is important for certain file system objects found on the host to be shared with the guest containers. Some notable examples are:

  • SSL certs (ie: /etc/ssl/certs)
  • hosts definitions (ie: /etc/hosts)
  • SSH keys (ie: /home/act_runner/.ssh)
  • common data folders (ie: /data)

I thought that the container.options value in the act_runner.yml config file used by the runner would allow these files and folders to be mounted to the containers via "-v /path/to/src:/path/to/target", but sadly this doesn't seem to be the case. I suspect this has something to do with the bug reported here but I'm not 100% sure.

Example Use Case 1
Suppose the host system has a set of static IP addresses defined in its /etc/hosts file, to allow host name resolution. This will allow those host names to resolve properly when operations are performed directly on the host, but not for operations that run inside Docker containers on that host.

This can present unusual problems when, say, the host name for the Gitea server can not be directly resolved because it prevents simple operations like Git checkouts to fail when run inside containers.

This can be worked around by manually mounting the hosts file from the host to the container at runtime, by using a config something like this in the project ./.gitea/workflow:

container:
    volumes:
        - /etc/hosts:/etc/hosts:ro

This is tedious to say the least because this change has to be made to EVERY SINGLE WORKFLOW ACTION running on the entire build farm.

Example Use Case 2
Suppose you have configured your Gitea service to use HTTPS using a self-signed SSL certificate. In that case you have to make the SSL certs available on all the hosts in your cluster and trust them so that HTTPS operations with those services work properly. This is particularly problematic when configuring independent servers to run the Gitea runners, because then not only do you need to share the certs across all runners, but you also need to somehow make them available within Docker containers running on those runners.

For example, if you have the SSL certs set up on the Gitea service itself, and on the hosts which run all the act_runners attached to the cluster, then you can create and register runners using secure HTTPS protocols, however any additional HTTPS operations performed within Docker images used by the builds running on those runners won't work.

The most obvious symptom of this problem is when you try to do a Git checkout operation within a build. Even though the runner is connected via HTTPS, the Git checkout operation will fail due to unrecognized SSL certificates.

Once again, this can be worked around by manually mounting the SSL certs folder from the host to the Docker container used by the build, something like:

container:
    volumes:
        - /etc/ssl/certs:/etc/ssl/certs:ro

However, just as I mentioned in my previous example use case, this creates a significant amount of bloat because then EVERY SINGLE WORKFLOW ACTION running on the entire build farm will have to have the same boilerplate config.

This use case is even more problematic than the previous one imo because without performing this hack I don't believe there is any way to enable complete end-to-end SSL encryption to all network traffic between the Gitea server and the runners when using a self signed certificate. (if there is an alternative solution for this, I would love to know what it is)

Example Use Case 3
Suppose you have some common sample data, like shared binary files or reference data, on each of the act-runner hosts and you want to make that data available to all the builds running on the cluster. Right now you'd have to do that on a per-action basis as described previously:

container:
    volumes:
        - /data:/data:ro

This example use case is also very problematic because, suppose you want to relocate the locate for the sample data to another location, say /sample/data. In order to facilitate such a change you would need to audit all actions defined on all jobs on the cluster to see which ones are using this shared volume and then update them ALL to reflect the change.

If, by contrast, this configuration could be defined once in the act-runner.yaml config file, then you would only need to make the change in one place and then all actions run on those runners will just work on their next run without further modification.

When running an action in Gitea which make use of of Docker containers for their builds, it is important for certain file system objects found on the host to be shared with the guest containers. Some notable examples are: - SSL certs (ie: /etc/ssl/certs) - hosts definitions (ie: /etc/hosts) - SSH keys (ie: /home/act_runner/.ssh) - common data folders (ie: /data) I thought that the container.options value in the act_runner.yml config file used by the runner would allow these files and folders to be mounted to the containers via "-v /path/to/src:/path/to/target", but sadly this doesn't seem to be the case. I suspect this has something to do with the bug reported [here](https://gitea.com/gitea/act_runner/issues/265) but I'm not 100% sure. **Example Use Case 1** Suppose the host system has a set of static IP addresses defined in its /etc/hosts file, to allow host name resolution. This will allow those host names to resolve properly when operations are performed directly on the host, but not for operations that run inside Docker containers on that host. This can present unusual problems when, say, the host name for the Gitea server can not be directly resolved because it prevents simple operations like Git checkouts to fail when run inside containers. This can be worked around by manually mounting the hosts file from the host to the container at runtime, by using a config something like this in the project ./.gitea/workflow: ``` container: volumes: - /etc/hosts:/etc/hosts:ro ``` This is tedious to say the least because this change has to be made to EVERY SINGLE WORKFLOW ACTION running on the entire build farm. **Example Use Case 2** Suppose you have configured your Gitea service to use HTTPS using a self-signed SSL certificate. In that case you have to make the SSL certs available on all the hosts in your cluster and trust them so that HTTPS operations with those services work properly. This is particularly problematic when configuring independent servers to run the Gitea runners, because then not only do you need to share the certs across all runners, but you also need to somehow make them available within Docker containers running on those runners. For example, if you have the SSL certs set up on the Gitea service itself, and on the hosts which run all the act_runners attached to the cluster, then you can create and register runners using secure HTTPS protocols, however any additional HTTPS operations performed within Docker images used by the builds running on those runners won't work. The most obvious symptom of this problem is when you try to do a Git checkout operation within a build. Even though the runner is connected via HTTPS, the Git checkout operation will fail due to unrecognized SSL certificates. Once again, this can be worked around by manually mounting the SSL certs folder from the host to the Docker container used by the build, something like: ``` container: volumes: - /etc/ssl/certs:/etc/ssl/certs:ro ``` However, just as I mentioned in my previous example use case, this creates a significant amount of bloat because then EVERY SINGLE WORKFLOW ACTION running on the entire build farm will have to have the same boilerplate config. This use case is even more problematic than the previous one imo because without performing this hack I don't believe there is any way to enable complete end-to-end SSL encryption to all network traffic between the Gitea server and the runners when using a self signed certificate. (if there is an alternative solution for this, I would love to know what it is) **Example Use Case 3** Suppose you have some common sample data, like shared binary files or reference data, on each of the act-runner hosts and you want to make that data available to all the builds running on the cluster. Right now you'd have to do that on a per-action basis as described previously: ``` container: volumes: - /data:/data:ro ``` This example use case is also very problematic because, suppose you want to relocate the locate for the sample data to another location, say /sample/data. In order to facilitate such a change you would need to audit all actions defined on all jobs on the cluster to see which ones are using this shared volume and then update them ALL to reflect the change. If, by contrast, this configuration could be defined once in the act-runner.yaml config file, then you would only need to make the change in one place and then all actions run on those runners will just work on their next run without further modification.
Author

One more problematic case that came to mind for me has to do with platform differences. Suppose, for example, that you have act-runners set up on multiple platforms (Windows, Mac, Linux)... and suppose you have a build which runs all of its operations inside a Docker container (ie: using a label like "docker"). It is feasible that all 3 of these platforms could have that label because they all support the Docker runtime.

In this case, there would be no way to define a set of volumes within any given build action that would be correct on all 3 of these platforms. For example, the locations for SSL certs will be different on all 3 of these OSes.

If, however, the default bind-mounts were specified in each of the act-runner.yml config files on each of those runners, they could all be customized according to their respective platforms, In this way, a Docker based container build could run on all 3 platforms without additional customization.

One more problematic case that came to mind for me has to do with platform differences. Suppose, for example, that you have act-runners set up on multiple platforms (Windows, Mac, Linux)... and suppose you have a build which runs all of its operations inside a Docker container (ie: using a label like "docker"). It is feasible that all 3 of these platforms could have that label because they all support the Docker runtime. In this case, there would be no way to define a set of volumes within any given build action that would be correct on all 3 of these platforms. For example, the locations for SSL certs will be different on all 3 of these OSes. If, however, the default bind-mounts were specified in each of the act-runner.yml config files on each of those runners, they could all be customized according to their respective platforms, In this way, a Docker based container build could run on all 3 platforms without additional customization.

I've already posted my own fix 3 months ago to the issue you've mentioned.
Nobody commented...

Now I've created a PR here, hope it will be merged 😉

I've already posted my own fix 3 months ago to [the issue](https://gitea.com/gitea/act_runner/issues/265#issuecomment-744382) you've mentioned. Nobody commented... Now I've created a PR [here](https://gitea.com/gitea/act/pulls/80), hope it will be merged 😉

I am to new with gitea to determine the best way to solve it, but yes I definitely need a way to use self signed certs between runner and gitea.

I am to new with gitea to determine the best way to solve it, but yes I definitely need a way to use self signed certs between runner and gitea.
Sign in to join this conversation.
No Milestone
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: gitea/act_runner#378
No description provided.