gregtwallace / certwarden

Cert Warden is a centralized ACME Client. It provides an API for certificate consumers to fetch their individual keys and certs with API keys.
https://www.certwarden.com/
Other
183 stars 6 forks source link

Add Dockerfile #3

Closed kantlivelong closed 1 year ago

kantlivelong commented 1 year ago

Hello :wave:

This PR adds container support! I wanted to try this out but preferred using a container over locally with the tgz. Haven't had a chance to test functionality yet but the container starts and I can login. This can be added to the pipeline to create (and maybe push?!) to a registry. Should also make supporting different cpu architectures easier.

Example build: docker build --build-arg=BACKEND_VERSION=v0.7.0 --build-arg=FRONTEND_VERSION=v0.7.0 -t legocerthub:v0.7.0 .

Example run: docker run -d --name legocerthub -p 4050:4050 -p 4060:4060 legocerthub:v0.7.0

Additional volumes/binds will likely make sense on exec. IE: docker run -d --name legocerthub -v /some/local/path/config.yaml:/app/config.yaml -p 4050:4050 -p 4060:4060 legocerthub:v0.7.0

Cheers :beers:

gregtwallace commented 1 year ago

This is super awesome thanks! I started to fiddle around with Docker myself after the Reddit suggestions and it actually led to: https://github.com/gregtwallace/legocerthub-backend/commit/0089371fee5a82c5e8a181831113b6feffcbf0b3

Though my Dockerfile is currently an ugly mess and only builds the backend.

I was inclined to add: VOLUME /home/nonroot/data edit: I'm using gcr.io/distroless/base-debian11 as the base, which presumably relates to the path name

to the Dockerfile to persist the data. What do you think?

In general, I'm planning to make any needed adjustments to support Docker and release v0.8.0 with a docker option.

kantlivelong commented 1 year ago

Adding volume tags would definitely make sense once things are broken out of the /app dir.

I personally prefer the following when applicable:

/app
/config
/data
/log

I used Alpine to keep footprint low (~26MB in my case) but the catch is that things like bash, curl, dig, etc.. aren't installed by default. A few options for that are:

  1. Install as part of the Dockerfile. Maybe ~40mb or so increase for the above.
  2. Require users ensure they are installed as part of their scripts. IE apk add X. bash might be a given thing to include though.
  3. Require users build upon the image using their own Dockerfile +/- Compose.

I did have one question that I thought of last night - Does the backend require the frontend be present in order to build or can I just skip that copy step in the backend build?

gregtwallace commented 1 year ago

They both build completely independently.

kantlivelong commented 1 year ago

Ah cool, just pushed a minor change to reduce copying.

gregtwallace commented 1 year ago

I think a slight revision:

RUN sh -c "mkdir /app/data"
RUN sh -c "printf \"%s\n\" \
  \"'bind_address': ''\" \
  \"'hostname': 'localhost'\" \
  > \
  /app/data/config.yaml"

EXPOSE 4050/tcp
EXPOSE 4055/tcp
EXPOSE 4060/tcp

The other issue that dawned on me is that hostname should really be specified. localhost is a decent starting place but only if the user is accessing the app initially from the same host. I'm not sure the best way to get the proper fqdn into the config at the outset.

Any ideas? Alternatively, could just warn users to edit config.yaml before first run (which they should probably be doing anyway).

kantlivelong commented 1 year ago

What is hostname used for (other than possibly previously being used as the bind address)? Sorry if is a stupid question I haven't had time to even set this up yet. :laughing:

Hostnames can be set in containers but it's usually the exception rather than the rule.

One option a lot of apps will do is accept both config value or environment variables. Something like LEGOCERTHUB_BIND_ADDRESS, LEGOCERTHUB_HOSTNAME, etc...

gregtwallace commented 1 year ago

The fronted has an env.is file that contains a variable to set the url for the backend. Essentially the front end React app loads on the users’ computer and then makes api calls to that url.

When the back end hosts the front end it creates env.js on startup. The url is constructed with the host name.

I broke out bind address because I wanted to be able to specify a specific address that might not necessarily be the client resolvable fqdn.

gregtwallace commented 1 year ago

The fronted has an env.is file that contains a variable to set the url for the backend. Essentially the front end React app loads on the users’ computer and then makes api calls to that url.

When the back end hosts the front end it creates env.js on startup. The url is constructed with the host name.

I broke out bind address because I wanted to be able to specify a specific address that might not necessarily be the client resolvable fqdn.

kantlivelong commented 1 year ago

Would it make sense to have the react app listen at / and then have the backend be routed through /api? No need to even know the hostname/FQDN then.

gregtwallace commented 1 year ago

Derp. I don't know why I didn't think of the most obvious answer.

Fixed: https://github.com/gregtwallace/legocerthub-backend/commit/5adfa6ec2c68e43eed489add7ab44a0389df2df3

The additional port should still be exposed though.

kantlivelong commented 1 year ago

Nice! I've rebased from master(Guess I really didn't need to but hey!), adjusted the bind var, added the additional tcp port. and squashed my commits.

gregtwallace commented 1 year ago

My bad, I also forgot the config path needs to be updated to /app/data

You could also update the bins address to blank which will ensure binding to both IPv4 and IPv6.

I’ll merge this tonight with those tweaks. I’ll probably wait on the next release until I add an update check functionality.

kantlivelong commented 1 year ago

Pushed, hopefully that's what you were referring to :smile:

gregtwallace commented 1 year ago

Got it, thanks!