github-action icon indicating copy to clipboard operation
github-action copied to clipboard

Proposal: Add support for custom base image repository in the Dockerfile

Open matiasAS opened this issue 1 year ago • 14 comments

Description of the problem I have been encountering rate limit errors when pulling images from Docker Hub. To address this, I'm using a Harbor project as a cache. It would be helpful to modify the Dockerfile in the GitHub Action to allow customizing the base image repository.

Proposal Modify the Dockerfile to allow the use of a custom repository for the FROM statement, like this:

ARG REPOSITORY FROM ${REPOSITORY}/dokku/ci-docker-image:0.13.0

Add a new optional parameter, REPOSITORY, to the GitHub Action.

  • If the REPOSITORY variable is provided, it should be used in the FROM statement.
  • If it’s empty, it should default to:

FROM dokku/ci-docker-image:0.13.0

Also add the credential configuration to access, in my case project cache in private harbor. As a temporary solution I have created a public project and with that I do not have an authentication error:

image

Expected Results

  • Users can configure the REPOSITORY in the GitHub Action inputs.
  • If the REPOSITORY is not set, the action should default to using dokku/ci-docker-image:0.13.0 from Docker Hub.

@josegonzalez i from Chile,

Regards Saludos

matiasAS avatar Sep 22 '24 16:09 matiasAS

I don't think this is a possibility with github actions. Do you know of another composite action that does what you are asking for?

josegonzalez avatar Sep 23 '24 04:09 josegonzalez

I forked the repository, modified the dockerfile, and then in actions changed it to my repository

@josegonzalez Is there a possibility of speaking more directly in Spanish?

matiasAS avatar Sep 23 '24 15:09 matiasAS

Feel free to post in spanish and I'll try and respond.

josegonzalez avatar Sep 23 '24 20:09 josegonzalez

gracias @josegonzalez Intentaré explicarlo mejor Uso dokku hace casi 1 año Despliego con github actions , tengo mi cluster k0s y ahi actions runner controller para runners self hosted.

El error de la imagen ya lo solucioné. Trabajo solo, necesito tener los menores costos posibles, y puede que contratar Docker pro sea la solución más rapida, pero obté por probar harbor. La idea del proyecto cache de harbor es que al hacer pull de la imagen, docker primero va a harbor y si no la encuentra a docker hub y hace una copia en harbor para que la proxima vez la obtenga de harbor. Pero para que esto funcione es necesario adelante de la imagen agregar el repositorio docker de harbor. Por eso que el dockerfile en vez de ser

FROM dokku/ci-docker-image:0.13.1

deberia ser

FROM <repositorio-harbor>/dokku/ci-docker-image:0.13.1

Con el fork del repositorio, y referencandolo en el workflow de github actions, funciona, pero lo que decia es que en la confuguracion de la action dokku/github-action@master esté el parametro de configurar ese repositorio en el dockerfile para no usar la opción forkeada y perder las actualizaciones

matiasAS avatar Sep 23 '24 20:09 matiasAS

Tienes un ejemplo de otro composite github action que usa un parametro para el docker image? Yo no creo que eso funciona como quieres.

josegonzalez avatar Sep 23 '24 22:09 josegonzalez

Nunca he construido ni manipulado un gihub action desde que empezé a usarlo, pocos meses, en lo primero que pienso es un build ardg porque en el workflow se hace build de la imagen, entonces ahi seria pasarle el parametro

matiasAS avatar Sep 23 '24 22:09 matiasAS

No se puede utilizar build args en el workflow. El documentacion esta acqui: https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-docker-container-action

Lo que quieres hacer no es posible en github actions.

josegonzalez avatar Sep 23 '24 22:09 josegonzalez

probaré igual en el fork

action.yml

name: 'Hello World'
description: 'Greet someone and record the time'
inputs:
  who-to-greet:  # id of input
    description: 'Who to greet'
    required: true
    default: 'World'
outputs:
  time: # id of output
    description: 'The time we greeted you'
runs:
  using: 'docker'
  image: 'Dockerfile'
  args:
    - ${{ inputs.who-to-greet }}

matiasAS avatar Sep 23 '24 23:09 matiasAS

Hola @josegonzalez , encontré una step que hace lo que me gustaría que hiciera esta step!!, https://github.com/dokku/github-action

en los with, parametro opcional "image", y en el workflow se hace pull desde ahi.

Saludos

matiasAS avatar Sep 26 '24 13:09 matiasAS

@josegonzalez

actions.yml

`--- name: "Dokku Deployment Action" description: "Deploy apps to a Dokku installation with dynamic Docker image support" author: "Your Name" branding: icon: "upload-cloud" color: "blue"

inputs: image: description: "Docker image to use for deployment (default: dokku/ci-docker-image:0.13.1)" default: "dokku/ci-docker-image:0.13.1" required: false branch: description: "The branch to deploy when pushing to Dokku (default: master)" required: false default: "master" ci_branch_name: description: "The command to run for the action (default: detected from GITHUB_REF)" required: false default: "" ci_commit: description: "The commit SHA that will be pushed (default: detected from GITHUB_SHA)" required: false default: "" command: description: "The command to run for the action (default: deploy)" required: false default: "deploy" deploy_docker_image: description: "A Docker image to deploy via git:from-image" required: false default: "" deploy_user_name: description: "A username to use when deploying a Docker image" required: false default: "" deploy_user_email: description: "The email to use when deploying a Docker image" required: false default: "" git_push_flags: description: "A string containing a set of flags to set on push" required: false default: "" git_remote_url: description: "The Dokku app's git repository URL (in SSH format)" required: true review_app_name: description: "The name of the review app to create or destroy" required: false default: "" ssh_host_key: description: "The results of running ssh-keyscan -t rsa $HOST" required: false default: "" ssh_private_key: description: "A private SSH key that has push access to your Dokku instance" required: true ssh_passphrase: description: "Passphrase to use when interacting with an SSH key that has a passphrase" required: false default: "" trace: description: "Allows users to debug what the action is performing by enabling shell trace mode" required: false default: ""

Running the action using Node.js runs: using: 'node20' main: 'dist/index.js' `

src/context.ts

import * as core from '@actions/core';

export interface Inputs { image: string; branch: string; ci_branch_name: string; ci_commit: string; command: string; deploy_docker_image: string; deploy_user_name: string; deploy_user_email: string; git_push_flags: string; git_remote_url: string; review_app_name: string; ssh_host_key: string; ssh_private_key: string; ssh_passphrase: string; trace: string; }

export function getInputs(): Inputs { return { image: core.getInput('image') || 'dokku/ci-docker-image:0.13.1', branch: core.getInput('branch') || 'master', ci_branch_name: core.getInput('ci_branch_name') || '', ci_commit: core.getInput('ci_commit') || '', command: core.getInput('command') || 'deploy', deploy_docker_image: core.getInput('deploy_docker_image') || '', deploy_user_name: core.getInput('deploy_user_name') || '', deploy_user_email: core.getInput('deploy_user_email') || '', git_push_flags: core.getInput('git_push_flags') || '', git_remote_url: core.getInput('git_remote_url'), review_app_name: core.getInput('review_app_name') || '', ssh_host_key: core.getInput('ssh_host_key') || '', ssh_private_key: core.getInput('ssh_private_key'), ssh_passphrase: core.getInput('ssh_passphrase') || '', trace: core.getInput('trace') || '' }; } `

src/main.ts

`import * as context from './context'; import * as core from '@actions/core'; import {Docker} from '@docker/actions-toolkit/lib/docker/docker'; import * as actionsToolkit from '@docker/actions-toolkit';

actionsToolkit.run(async () => { const input: context.Inputs = context.getInputs(); core.info(Git Remote URL: ${input.git_remote_url});

core.exportVariable('IMAGE', input.image); core.exportVariable('BRANCH', input.branch); core.exportVariable('CI_BRANCH_NAME', input.ci_branch_name); core.exportVariable('CI_COMMIT', input.ci_commit); core.exportVariable('COMMAND', input.command); core.exportVariable('DEPLOY_DOCKER_IMAGE', input.deploy_docker_image); core.exportVariable('DEPLOY_USER_NAME', input.deploy_user_name); core.exportVariable('DEPLOY_USER_EMAIL', input.deploy_user_email); core.exportVariable('GIT_PUSH_FLAGS', input.git_push_flags); core.exportVariable('GIT_REMOTE_URL', input.git_remote_url); core.exportVariable('REVIEW_APP_NAME', input.review_app_name); core.exportVariable('SSH_HOST_KEY', input.ssh_host_key); core.exportVariable('SSH_PRIVATE_KEY', input.ssh_private_key); core.exportVariable('SSH_PASSPHRASE', input.ssh_passphrase); core.exportVariable('TRACE', input.trace);

await core.group(Docker info, async () => { await Docker.printVersion(); await Docker.printInfo(); });

await core.group(Pulling Docker image for deployment, async () => { await Docker.getExecOutput(['pull', input.image], { ignoreReturnCode: true }).then(res => { if (res.stderr.length > 0 && res.exitCode != 0) { throw new Error(res.stderr.match(/(.)\s$/)?.[0]?.trim() ?? 'unknown error'); } }); });

await core.group(Deploying the app, async () => { await Docker.getExecOutput( [ 'run', '--rm', '-v', ${process.env.GITHUB_WORKSPACE}:/github/workspace, // Monta el repositorio en /workspace '-w', '/github/workspace', '-e', SSH_PRIVATE_KEY=${input.ssh_private_key}, '-e', GIT_REMOTE_URL=${input.git_remote_url}, '-e', BRANCH=${input.branch}, '-e', CI_BRANCH_NAME=${input.ci_branch_name}, '-e', CI_COMMIT=${input.ci_commit}, '-e', COMMAND=${input.command}, '-e', DEPLOY_DOCKER_IMAGE=${input.deploy_docker_image}, '-e', DEPLOY_USER_NAME=${input.deploy_user_name}, '-e', DEPLOY_USER_EMAIL=${input.deploy_user_email}, '-e', GIT_PUSH_FLAGS=${input.git_push_flags}, '-e', REVIEW_APP_NAME=${input.review_app_name}, '-e', SSH_HOST_KEY=${input.ssh_host_key}, '-e', SSH_PASSPHRASE=${input.ssh_passphrase}, '-e', TRACE=${input.trace}, input.image, 'dokku-deploy', input.git_remote_url, input.branch ], { ignoreReturnCode: true } ).then(res => { if (res.stderr.length > 0 && res.exitCode != 0) { throw new Error(res.stderr.match(/(.)\s$/)?.[0]?.trim() ?? 'unknown error'); } }); }); });`

package.json

{ "name": "dokku-github-action", "description": "Dokku GitHub Action for deploying apps", "main": "src/main.ts", "scripts": { "build": "ncc build src/main.ts --source-map --minify --license licenses.txt", "lint": "npm run prettier && npm run eslint", "format": "npm run prettier:fix && npm run eslint:fix", "eslint": "eslint --max-warnings=0 .", "eslint:fix": "eslint --fix .", "prettier": "prettier --check ".//*.ts"", "prettier:fix": "prettier --write ".//*.ts"", "test": "jest" }, "repository": { "type": "git", "url": "git+https://github.com//.git" }, "keywords": [ "actions", "dokku", "deployment" ], "author": "Tu Nombre", "license": "Apache-2.0", "dependencies": { "@actions/core": "^1.10.1", "@docker/actions-toolkit": "^0.35.0" }, "devDependencies": { "@types/node": "^20.12.12", "@typescript-eslint/eslint-plugin": "^7.9.0", "@typescript-eslint/parser": "^7.9.0", "@vercel/ncc": "^0.38.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.5.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.7.0", "prettier": "^3.2.5", "ts-jest": "^29.1.2", "ts-node": "^10.9.2", "typescript": "^5.4.5" } }

lo hice guiandome por la step :

   - name: Set up QEMU
    uses: docker/setup-qemu-action@v3
    with:
      image: <imagen>
      
     
     Saludos

matiasAS avatar Sep 26 '24 18:09 matiasAS

@josegonzalez lo que hice funciona sin problemas!, puedo especificar mi imagen apuntando a harbor como queria!!!

matiasAS avatar Oct 02 '24 03:10 matiasAS

Puedes hacer un PR?

josegonzalez avatar Oct 03 '24 14:10 josegonzalez

@josegonzalez si claro, no hay problema

matiasAS avatar Oct 03 '24 14:10 matiasAS

@josegonzalez listo!

matiasAS avatar Oct 03 '24 14:10 matiasAS