Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an official dockerfile #887

Merged
merged 6 commits into from
Dec 3, 2018
Merged

Conversation

brownleej
Copy link
Contributor

We've had previous discussions and PRs about this, but I wanted to give it a fresh start. This image is taken from my local testing setup, and I think it is suitable for general testing use. I've tried to keep it pretty simple so that we can iterate on it and get it to something that we can commit to as a stable image.

Copy link
Contributor

@alexmiller-apple alexmiller-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize for the slow review.

I am all for any amount of incremental progress in this area, and having a docker image available for local testing sounds like a great improvement. #355 seemed to have a broader goal of supplying a docker image that could be used to run FDB in "production". Did you have a solid enough understanding of #355 to be able to describe what features existed in that PR that aren't present in this one (if any)? Is there any plan as to what will or will not be supported?

RUN chmod u+x fdb*
RUN mv fdb* /usr/bin
WORKDIR /var/fdb
RUN rm -r tmp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these sorts of chains of commands supposed to be in one RUN line and chained with && ? I honestly don't understand dockerfile best practices.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. That's the case because every RUN or any other command creates a new layer, which usually results in bigger overall image size. Just to illustrate:

...
ADD $FDB_WEBSITE/downloads/$FDB_VERSION/linux/fdb_$FDB_VERSION.tar.gz .
RUN tar -xzf fdb_$FDB_VERSION.tar.gz --strip-components=1
RUN rm fdb_$FDB_VERSION.tar.gz
RUN chmod u+x fdb*
RUN mv fdb* /usr/bin
WORKDIR /var/fdb
RUN rm -r tmp
...

Every line creates a new layer, meaning that even if have done rm fdb_$FDB_VERSION.tar.gz and rm -r tmp, the intermediate layers would still keep this files. This is effectively just a junk, because no one can access this file in the final image. Hence it's recommended to produce fewer number of layers by chaining commands:

RUN wget $FDB_WEBSITE/downloads/$FDB_VERSION/linux/fdb_$FDB_VERSION.tar.gz \
 && tar -xzf fdb_$FDB_VERSION.tar.gz --strip-components=1 \
 && rm fdb_$FDB_VERSION.tar.gz \
 && chmod u+x fdb* \
 && mv fdb* /usr/bin \
 && cd /var/fdb \
 && rm -r tmp

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've restructured the dockerfile a bit to reduce the number of layers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also thinking that in a future enhancement we may want to use a multistage build and just copy the binaries and libraries from an earlier stage into the final stage to reduce layering.

# limitations under the License.
#

source $(/var/fdb/scripts/create_server_environment.bash)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm finding this a little weird for a couple reasons:

  1. The failure handling here seems a little questionable. create_server_environment.bash will fail by outputting an error message, and then exit 1. This line will then try to execute that error message and source it.
  2. create_server_environment.bash has a lot more side-effects than things that I generally see used in this form.

I'd suggest outputting to stderr in your scripts, which should just be tacking on a 1>&2 to the end of your echo lines for error messages.

However, reading through the PR further, I see why you preferred to have them as separate files instead of a library of code to source, as then it's easy to copy a single script to re-use and run in the client. However, calling it as a process and not as a library means that the exit 1 doesn't kill the current process as well, as it probably should.

You can either solve this via running set -e beforehand, which I've generally found to be brittle, or stealing a trick to be able to distinguish sourced vs directly run files, similar to python's if __name__ == '__main__'

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi

so that you can use the scripts either as callable standalone, or source-able and callable as a function.

Does that seem any better to you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I've moved the cluster file creation logic into a function and redirected more outputs to standard error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I had actually meant this line though. I see that you've moved create_cluster_file into a source-able function, but if /var/fdb/scripts/create_server_environment.bash does exit 1, we'll end up running source, which errors, and then continue onto starting up fdbserver below. I think it'd be clearer if we could just exit here. Could you do the same transformation to create_server_environment?

Add more copyright headers to the docker sample files.
Make the cluster file creation logic in the docker image into a function.
Copy link
Contributor

@bluk bluk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried out this branch to attempt some automation. Hope you don't mind the random comments.


The port that FoundationDB should bind to. The default is 4500.

### FDB_NETWORKING
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to have changed from FDB_NETWORKING to FDB_NETWORKING_MODE.

Suggested change
### FDB_NETWORKING
### FDB_NETWORKING_MODE


This directory provides a Docker image for running FoundationDB.

The image in this directory is based on Ubuntu 18.0.4, but the commands and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nitpick.

Suggested change
The image in this directory is based on Ubuntu 18.0.4, but the commands and
The image in this directory is based on Ubuntu 18.04, but the commands and

public_ip=127.0.0.1
FDB_CLUSTER_FILE_CONTENTS="docker:docker@$public_ip:4500"
elif [[ "$FDB_NETWORKING_MODE" == "container" ]]; then
public_ip=$(grep `hostname` /etc/hosts | sed -e "s/\s *`hostname`.*//")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the FDB_CLUSTER_FILE_CONTENTS be set here as well? I tried:

docker build . -t fdb:latest --build-arg FDB_VERSION=5.2.5
docker run -ti --rm -e "FDB_NETWORKING_MODE=container" -e "FDB_PORT=4500" fdb:latest

I got:

Starting FDB server on 172.17.0.2:4500
Invalid cluster file `/var/fdb/fdb.cluster': 2104 Connection string invalid
Error: Connection string invalid

Adding the FDB_CLUSTER_FILE_CONTENTS line 32 in this elsif block seemed to make things better but I'm not too familiar with FDB to know if this should have been written out by default and should "just work" or my setup is just wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good catch! I think I was trying to accomplish this through the FDB_COORDINATOR option, but the DNS resolution wasn't working properly, so I've tweaked this to use FDB_CLUSTER_FILE_CONTENTS in both networking modes.

ARG FDB_WEBSITE=https://www.foundationdb.org

WORKDIR /var/fdb/tmp
RUN wget $FDB_WEBSITE/downloads/$FDB_VERSION/linux/fdb_$FDB_VERSION.tar.gz && \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to consider adding a SHA256 checksum check here. Adding another argument after line 31 like:

ARG FDB_VERSION_SHA256SUM 

and then running the check in the RUN block on line 35.

RUN wget $FDB_WEBSITE/downloads/$FDB_VERSION/linux/fdb_$FDB_VERSION.tar.gz && \
    echo "${FDB_VERSION_SHA256SUM} fdb_${FDB_VERSION}.tar.gz" > checksum && sha256sum -c checksum && \
    tar -xzf fdb_$FDB_VERSION.tar.gz --strip-components=1 && \

Then running:

docker build . -t fdb:latest --build-arg FDB_VERSION=5.2.5 --build-arg FDB_VERSION_SHA256SUM=275b9f541590d145136061cee6427103b347e1ff0e851b6556671e46102c1ad9

Just a "maybe nice to have".

@ofek
Copy link
Contributor

ofek commented Nov 20, 2018

@brownleej Thanks so much for doing this! Do you think you'll have time this week to address the final review comments?

@mexisme
Copy link

mexisme commented Nov 21, 2018

I'm also thinking that in a future enhancement we may want to use a multistage build and just copy the binaries and libraries from an earlier stage into the final stage to reduce layering.

I'd love to see that.
I might be able to do a follow-up PR for it, if that helps?

…the docker image for the two different networking options.

Fixes some inaccurate text in the docker image README.
…urceable function.

Adds an explicit coordinator container in the docker-compose sample to support recent changes in the name generation in docker-compose.
Bump a dependency version in the dockerfile.
Improves handling of coordinator lookup failures in the docker scripts.
Copy link
Contributor

@alexmiller-apple alexmiller-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you still want @AlvinMooreSr to approve, or are we good to merge?

@ofek
Copy link
Contributor

ofek commented Nov 30, 2018

This is very exciting! Will an image be released soon after merging as well?

@jdotjdot
Copy link

Not only an image, but if there were instructions on how to start a production-ready multi-node FoundationDB cluster with Docker, that would be great. Given the lack of an existing AMI/Cloudformation/Terraform set up, at least with this Docker image, a docker-compose, Docker Swarm, or Kubernetes example template could be set up.

@alexmiller-apple
Copy link
Contributor

@jdotjdot There was an example of terraform scripts posted on the forums.

Copy link
Contributor

@AlvinMooreSr AlvinMooreSr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@brownleej
Copy link
Contributor Author

@jdotjdot We're definitely interested in building out more examples on how you would run this image in production on something like Kubernetes. I'm hoping to be able to put something like that together this month; it will probably go along with more work on the image itself.

@brownleej brownleej merged commit 33d2ad5 into apple:master Dec 3, 2018
@lxcid
Copy link

lxcid commented Dec 3, 2018

Looking forward to it!

etschannen pushed a commit to etschannen/foundationdb that referenced this pull request Mar 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants