My name is Laura Frank. I'm a senior engineer at CenturyLink Labs. We're a pretty small R&D offshoot of CenturyLink proper, so we don't really deal with any telephone polls or cable subscriptions, but what we do is a lot of R&D around Docker and the technologies that are kind of tangentially related to Docker like Fleet, CoroS, Kubernetes, you may have heard some of these. We kind of look at how they're serving the development community, how we work with them, and then hopefully try to make them better. I'm on the internet, you can find me. I also share a name with a reporter from a Colorado newspaper. I'm not her. So like I said, I work with Docker a lot. Here I'm going to talk about Docker and Ruby together. Over the course of this talk, I'm going to try to answer three kind of large, ambitious questions for you. The first being, what are Docker containers? The second, how can you use Docker and Ruby together? And then finally, how might you architect an application using Docker and Ruby together and actually have it work? I assume that most of you have heard about Docker, but maybe know nothing about it, and that's just perfect. I'm going to go over a lot of the pretty basic introduction stuff to Docker. If you are a Docker user already, hopefully I'll shed some light on some of the technical underpinnings of Docker. I know last night there was a Docker boss. Did anyone attend that in the audience? A few? Okay. One guy? All right. I said like did not attend. I was stuffing my face full of fish because I live in the Midwest and it was pretty special. So what is Docker? We've probably heard about Docker because companies like Google, Spotify, Twitter, guilt group, countless others have been really talking a lot about how they're using Docker in production and all of the fun and complicated problems that it has solved for them. But the truth is that Docker is really not, or the idea of container-based virtualization is not really anything new. LXC or Linux containers has been around since 2008. But Docker kind of puts this nice, pretty front-end on it and it makes it a lot easier for everyone to use it. And also, as more people are using the Internet all the time, these production workloads can fail at a much more rapid pace than maybe they were before everyone was on their smartphones all the time. So Docker has this really big need that it can fill. So Docker at its core is a packaging tool. It sits on top of existing components of the Linux kernel and packages these containers and puts them into isolated execution environments. That's really all that it is. Docker has a very limited scope. It does not schedule jobs for you. There are lots of things that it does not do for you. What it does do for you is package your stuff and put it in a container. And a container really is nothing more than just a self-contained execution environment. I'm going to talk about how exactly this is set up in just a little bit, but think about it as something in a box that is isolated from everything else around it. It has the benefit of having the shared kernel of the host system that it's on with having isolation. So they're sharing and isolation, those things together give it a very fast boot time and low overhead and also makes things work very efficiently because you're getting rid of a lot of duplicitous work. And in fact, you will see a big performance benefit from a service that's running in a virtual machine or a service that's running in a container. And this is due to very, very big differences between how these services actually run on the host. So here's an example of a pretty typical virtual machine set up. Probably have something like this running right now. In this example, we have two different services. We have app one, which is one service, two instances of that service, and then app two. And they're in virtual machines. On each machine, there's the library. There's a guest OS. We have a hypervisor underneath all of those. Of course, sitting on a host OS and sitting on top of hardware. In the Docker world, though, we can get rid of the hypervisor. There's really no need for it. And we can get rid of the guest OS on every virtual machine. And instead, we're going to introduce something called the Docker engine. This is the actual packaging tool that's sitting on the host, putting things into containers and deploying them for you. You'll notice that the libraries now, instead of being in the container, are actually underneath the container. This lets each container that's identical reference back to the same library. There's no need to have duplicitous copies of everything. Maybe an easier way to understand it is at the San Diego Zoo. It was just there on Sunday. The koalas are all in their own little self-contained environments, but each koala does not need to have its own healthcare giver, and they have access to the same food supply. I mean, it would be really silly to have a separate veterinarian per koala. You kind of don't want to have a separate library for each of your container containers. Also, koalas are very cute. So, how does this work? Containers seem kind of very abstracted and maybe difficult to understand. And they are. I mean, we spent the last nine months working on a tool that sits on top of Docker, and we still kind of want to throw our laptops out the window most days. But there's really four big things that make Docker run the way that it does and give you all these great performance benefits. The first one is lib container. This is the container format. So, maybe several months ago, I don't know exactly remember when, but Docker launched lib container, which is its own equivalent to LXC. Previously, Docker was just building on top of LXC, which was why it could only run on Linux. But now, lib container is a different container format that's very, very similar to LXC, but actually has the capability of running anywhere. You can probably, if you pay attention to Docker blogs, you'll see that they're starting to think about running it on Windows. Maybe it can run on a Mac natively soon. It's all due to this lib container, container format. For our purposes, and the examples we'll look at today, we're just going to use lib container. We could use LXC. It's kind of a layer of complexity that we don't need to spend too much time on. The next thing, no, this is like the three really important things, namespaces. This is what makes the container isolated from everything else. So, this is process and not resource. So, this is networking. This is process ID or PID. All of these are happening in its little namespace so that it's not going to conflict with other containers that are on the same host. This is what puts it in its little partition. On the other side of that is a thing called C groups, which is a container group. This is what allows these containers to be good multi-tenant citizens and access shared resources when needed, like the library or the veterinarian if our containers are koalas. The last thing is the union file system. This is particularly what makes Docker very fast. The layered file system is the copy-on-write. Everything that happens when you're building the image to run your container from happens sequentially and everything is stacked and stacked and stacked. Think of it as your Git log. If you want to go and redo, maybe just rebuild something on your image, you can point it back at maybe three layers before and rebuild from there. You don't have to go all the way back and get rid of your Git directory and clone it again. You can just reference back and then build on top of it. Those are the technical things that make Docker this lightweight runtime and packaging tool using components of the Linux kernel. The other great thing about Docker, though, it's more than that. It's a development workflow and an ecosystem, which is why Docker is so attractive to developers working in small teams and developers working for companies that have production loads like Google. This is sort of what Docker looks like. On one hand, we have the engine, which is what I just talked about. That's all the technical stuff, the code execution, et cetera. On this other side, we have a hub. This is where people go to collaborate and share things with one another related to Docker. The cornerstone of this hub part of Docker is called the registry. You can find it at registry.hub.docker.com. It looks a little bit like this. This is what it looked like when we took the screenshot. This is where images go to live. If you work on a Docker image and you would like to share it with people, you can push it to this public registry. You can use a private registry if you have some proprietary images. It's a whole nother talk, though. You'll notice about a third of the way down, there are these things called official repositories. These are companies or communities that have been using Docker and say, it would be really great if we would just put an official image up here that people can use so they don't have to do the same work over and over again. For example, if you wanted to use MongoDB in your project, you don't have to build that image. Just use the one that MongoDB has put up there for you to use. Almost all of these, actually, all of them do have great documentation about bootstrapping your own project to use these official images. We have to install Docker before we can use it. This is one of my favorite tweets because Docker does get a lot of flak that it is very abstract things a lot, maybe too much for some people's comfort. There's many layers usually between the hands that are typing the code and the code that's actually running in a container, whatever that is, somewhere on a host. I'm not going to lie. It can be a hurdle to get over when you start using Docker. The good news is there's a lot of tools to help you kind of bridge that huge gap that it can feel like you have between you and your code. If you're on Linux, like I said before, Docker was built at first off of Linux containers, you can just install Docker with official packages and you can be ready to go. But if you're on anything else, you will have to run a VM. I realize that sounds maybe in vast contrast to what I just told you about how VMs are evil and bloated, but I guarantee that running one VM where you can run thousands of containers or hundreds of containers, depending on how big that VM is, is not really going to impact your performance very much. In fact, Docker has this great tool called Boot to Docker, and you can find that on Docker.com when you look in the installation instructions. It's basically a very lightweight tool that will spin up a VM for you in the background, get Docker running on it, make everything work for you, and it will sync all of your folders so that you can interact with Docker on your Mac or Windows machine, just like you're just on your normal terminal. I'm actually going to use this in my presentation. It will look like I am just typing and interacting with Docker directly. In fact, I'm using Boot to Docker and there is a layer of abstraction. Everything I'll do in this presentation is running on a Boot to Docker VM. When you do have Docker installed, maybe with Boot to Docker, maybe your own vagrant file, certainly whatever you prefer will work, you're going to interact with Docker, probably via the CLI. There's also a REST API for interacting with Docker, and both of these have extensive, wonderful, beautifully written prose documentation at docs.docker.com. All right, on to the good part. Using Ruby with Docker. So specifically, how might you use the API and the CLI and an image to make a container that's running Ruby and that can run your Ruby application? Before we really get into spinning containers up, we have to take a step back and really acquaint ourselves with what an image is. Think of a Docker image as the class and a container is an instance of that class. You have to have an image in order to start a container. You cannot start a container without an image. The container will have nothing in it. Each image is controlled by a Docker file. This is basically a list of instructions. We're going to look at a Docker file in just a few seconds and we're actually going to build an image together. It will be really fun. Images are built by saying Docker build dash t is for tag. And then you give it a name. Generally, a convention that's used is like your GitHub name slash name of your image. You can also just call it whatever you want. And then a dot to signify where the Docker file resides. Most often it will be in the directory that you're in. Going back to that Docker registry that I mentioned before, so whether or not it's a public registry or a private registry that you are running yourself, you can Docker pull an image down, pull it down just by using the name of the image, which again is usually the person's GitHub name and then the name of the image. Optionally, there is a tag for a version, which is a colon tag. We'll see this when we look at the Ruby image, which is right here. This is a Docker file. This is a very, very, very simple application. You can see that it's based off of 2.1.2. It does some stuff, and then eventually down here we have a command that we're going to start the container with. So why don't we build this? Maybe, hopefully it works. Okay. You guys can all see that? So I'm in this, sorry. In my directory I have kind of all the junk I need to run this application. Most notably, I have a Docker file, which is the same Docker file that we just looked at. So I am going to Docker build dash t. I'm just going to call this hello world and then a dot, because it's where I am now. And we can see this layered file system already in use. We can see step four, and it's giving us kind of the place in memory where all this stuff is stored. So this might take a little while. So while we do that, hopefully that works. Live coding or live demo is always a little nerve wracking for everyone involved, including the audience. So thank you, guys. Great. Again, this Docker file is super simple. The from command is a requirement. You have to have a base image that your image inherits from. So similar to that class object analogy that I used earlier, inheritance also works. So anything that the CenturyLink base image has will also be in my image because I am referencing it and pulling in all of its stuff. Notice the colon 2.1.2 because this is Ruby 2.1.2. You can use any version CenturyLink. We have spent a lot of time optimizing Ruby images. If you're interested in using them, you can find them on the hub at the CenturyLink repository. The next thing is maintainer. So that's me. And if it breaks, then you can blame me and know where to find me. The next thing is an expose command. This just kind of advertises that your service is available on a port. It will advertise that to other containers that are running on the same host. Next, we have a set of run and add. A run command will run the command that is passed to it. So in this case, we're going to make a directory, an app directory, and then add is basically like a copy command. So we're going to copy everything from the current directory into that new app directory that we just made. And then next, we will set that app directory as our working directory. From this point forward, everything that's passed to the Docker file via run happens in context of this work. So when we run bundle install, it's going to run specifically only the gem file that is in that directory that we just made.  This is command or cmd. So for this, we're just going to enter with like very basic ruby hello world.rb. And this is one more that's kind of important. You'll probably see it in a lot of the other Docker files that are available on Docker registry. This is an environment variable. It takes the syntax of key in upcase and then value in downcase. And any environment variable that you give it in the Docker file will be understood and known and used by any subsequent run command. And then the next one is volume. You can either say give it a path or you can give it an array of paths. This just creates a mount point. This is how you would get code into a container by creating a mounted volume of that code. And before we check on our image that's hopefully downloaded, this from thing is actually pretty powerful and really important and can take your Docker workflow from being like okay to being really super great. Basically in a perfect world, we'd be using the same version of Ruby in all of our services, hopefully. But really only one base image. You can reference that base image from other Docker files for other services that you're running. And then also, this has Ruby baked into it. You don't need to have a gem set manager or a version manager because there's just one thing. There's just one set of gems. There's just one version. It's baked into your base image. If you do want to update Ruby then, you can just update the base image and then that, again, it will be shared across everything. Okay, cool. Successfully built. That's excellent news. I'm just going to clear this for you in the back. That bottom part might be hard to see.  I think I had a partial failed build which is why I have this weird none none. But you can see that here. Century link Ruby base is actually treated as a whole separate image. Remember that's my base image.  And in fact, if we delete this hello world, I'm not going to do it right now. Actually, I think that would be a bad idea. And then rebuilt it, we would see that the work that Docker had to do to get that Ruby base image doesn't happen anymore. We don't need to do it. We've already stored it. We're just going to delete everything from the base image. And since the base image would be shared again because I'm running the same thing, it would just do the work whatever those seven instructions were after building the base image in order to kind of rebuild the same thing that I did before. So again, take translate that into maybe having multiple services that share the same base image. It's a lot of work that you can save by just putting all of your kind of inherited dependencies in that base image. So why don't we run this thing? That would be a great idea. The way to look for processes that are running on your host is Docker PSA that will give you all of the processes that are happening. And you can see we have nothing happening right now. So let's Docker run.  So that's dash P. And I'm just going to bind 4567 kind of to itself. And then the last argument I'll pass is the name of the image. And that was it. And now we have a containerized application running before your very eyes. So it really was... Thank you. So think about how long it took to run that. It was like literally milliseconds. Think about how long it might have taken a virtual machine to spin up and run that same application. Probably many, many milliseconds. Think about how many times you have to restart a container or restart a service over the course of your daily work when you're developing stuff. If you can shave that down from minutes down to milliseconds, you have a lot more time to look at cat pictures or whatever you want to do. So cool. We have this here. It's running. You know, I can see it. And then I'll just shut it down and we can see that container. Oops. Container is running. It's exited. We get exit codes for Docker containers. And if I wanted to start it again, I can either reference its identifier or its fun name, which in this case is High Shockly. It's always like some combination of adjective and like scientist or something. Usually this looks a little nicer. I just have the font blown up pretty big on here. All right. So that's it. That was running a Ruby application. Cool. So in this case, I used our own CenturyLink virtual image or base image. Ruby does have a lot of official images and they are up on the Docker hub. Pretty much anything 1.9.3 and newer you can grab. And again, just a Docker pull and really great instructions for bootstrapping. And like I said before, the base Ruby images, the official ones are a little big. Specifically, my team has spent a lot of time trying to make them very small. And eventually, I think we would love to have our images be the official Ruby images, but we're just not quite there yet. So you're welcome to use either, depending on what you want to do. And lastly, you might need some gems. Swipely has done a lot of work with Docker and they have a few really good gems. The one that we use for the projects that we work on is the Docker API gem. So this allows you to interact with the Docker API from inside of your application. If you go to Ruby gems, there's like 30, probably 35 other ones. Anything from building images to, you know, running Docker PSA and having a nice output of all the processes that are running on your host. So just poke around and some of them are obviously more developed than others and some of them have more users than others. But you could probably find anything that you need there. And also debugging in a container is kind of a pain. Sorry. Like I said before, Docker has a lot of kind of a lot of flak because it has so much abstraction between your code that's running like somewhere out in the ether on a container and you actually doing the work. What we found on our team is that we just, we use pry if we need to. We try to run things kind of locally before we put them in a container but that's not always really that possible. So I hope you're all using pry already and if you're not, require the thing and then call the thing and you'll be dropped into a nice debugging session and apparently you can time travel now with pry so I'm going to try that as soon as I get back to Chicago. The one piece of advice I have for all of you, if you're using pry, you may think, oh, it's in a container, it's away from me, I have to use a remote debugging session. You really don't need to in most cases. In some cases you might have a container running in the background and then you might have to set up a remote session. By and large, generally, if you're just kind of tinkering, you don't need a remote session. Alternatively, you can pass in the pry command directly to that Docker run string and be dropped into a debugging session with the Docker run name of the image and then after the image name, you can say pry, that's the equivalent to the command that we saw in the Docker file and you can just be dropped right in. So now that we know how to fix stuff that breaks, we could probably start putting some stuff together. So how do I build a thing with Docker? So let's talk about architecture, which is everyone's favorite topic usually. Docker architecture is service-oriented architecture, plain and simple. Think about how fast it was milliseconds to get that service running. That really is beneficial if you have just one service per container. You may look at a container and say, wow, this is really fast. It's taking up a lot less space. I can just dump everything into one container and then it'll be really fast and great, which is kind of true. But if you have each service in a different container, if any of those fail, you can spin it up very, very quickly.  So here we have a nice illustration of one service in one container. This is a very simple application. It has a web framework and then a database behind it. So we might look at this and say, okay, but a container is isolated. So how does container one know that container two exists? And furthermore, how can I even get them to exchange information with one another? And the answer to that is there's a few of them. You can link them together. I'm using something called the Docker link. But more commonly, you'll probably use some kind of combination of port mapping and then environment variables, depending on particularly what requirements your services have. All of this is just configuration. I mean, it's really nothing more than just configuration. And this configuration happens in two places. We've seen already that the Docker file can handle a lot of these options. That's baking them into actually the base image, like that class that then becomes the object, which is the container. But then also, you saw me just before make a port mapping rule in the Docker run string. So there's a lot of different flags that you can use in the Docker run string. And most of them kind of have shared work. You can either do it in the Docker file or you can do it at runtime. So let's take a look again at this dummy app and look at the Docker file. I'm going to try to help you understand maybe some best practices of what should go where in terms of making a choice between where you want your configuration options to live. So we have this Docker file. More or less, this is just fine. I don't have anything too specific or too particular. So for example, I might be using this for one reason, but if I put it on the Docker hub and have someone else use it, I don't know what they're going to be using it for. So I don't really want to hard code anything, like maybe a port binding rule. I don't want to put that in there. And I really, really don't want to put environment variables in the Docker file. It sounds funny to think about, but if you don't know maybe what you're doing, you might accidentally put something in a Docker file and commit it to GitHub or to the registry and then everyone has your password. So that is particularly one thing that you want to do just at runtime. Don't put that in the Docker file. So let's look at the kind of equivalent of that Docker file, but with a Docker run string. So again, Docker run. We have dash P here for the port binding rule or port mapping rule, whatever you like to call it. And then here is where your environment variables belong. This is dash E. You can put quotes around it or you cannot, depending on how you're feeling that day, I guess, always again, password and upcase equals and then unless your value is case sensitive, it should be in downcase and there should not be a space in between the equal sign. I think keynote just got a little ambitious there. And then finally, that linking thing that I talked about earlier. Docker has a capability for linking. You can say that one thing, in this case the web container that I'm running with a Docker run string depends on the database. And you give it a name and an alias. So DB, DB in this case. And then again, the last thing that you pass, if you're not passing a command, is the name of the image that you're actually running. And again, a word of caution about using a Docker link. When you're using Docker directly on your own host, that's great, you can use a Docker link. But if you're doing any kind of scaling, you might be using Kubernetes, you might be using Marathon and Mezos or Fleet with various service discovery components. That's not Docker. And it doesn't know what a Docker link is. So if you're going to have some kind of schedule, scheduler orchestrating your Docker containers, don't use a link. Use the environment variable and it's kind of like port mapping way instead. It's kind of advanced stuff. If you have any questions, of course you can talk about it later. But I won't take up any more time talking about it right now. So a little bit more about the Docker run string is that each container has its own. You can only run one container with one command. Multiple containers can use the same image to run from. It's not like you have to have a different image for each container. You can use the same image to run multiple containers. And again, you want to find the balance between the Docker run string and then the Docker file for configuration so that you're not exposing anything that shouldn't be exposed. But again, you have to do this whole configuration business every time you run a container. And I'm really lazy. That's why I became an engineer. And I would rather make a computer do the work for me than do it myself. And the good news is that you can do that with Docker. There's this idea called application templating and that's what my team and I spend our time working on is kind of the equivalent of forming up but for Docker containers. So if you understand and configure your container or your application once, you can put it into an application template and instead of running each container independently, you run the template that will take care of running all of the containers with the various configuration options that you've already specified. You can use your own images. You can use images from the Docker registry, specify your options beforehand so you don't need to, like, do them on the fly. And then, again, you can just run the application as a whole instead of running each container independently. So a popular one is FIG. This is actually a part of Docker proper now. It used to be its own thing and then Docker acquired them. And that's a great thing because that means that FIG standards are very tightly coupled with Docker standards. How it works is you dump your application requirements into a YAML file called fig.yaml and then run fig up and then your application is running for you. It's at fig.sh. And again, this is a proper Docker project and maintained by the Docker community. It is command line only, though. So if you're looking for something that is a little bit more visual as you first get started or maybe you prefer to work that way, the software that I work on with my team is called Panamax. And we have t-shirts, if you'd like one. It's a Docker workflow tool. It itself is a containerized application, depending on how you're using it. When you run Panamax, you'll actually be running anywhere from three to five at Ruby services in containers. Panamax does use a lot of these Ruby or Docker adjacent technologies like CoreOS, Fleet at CD for things like service orchestration and service discovery. And you can find us and all that good stuff at panamax.io. So Panamax on purpose, we made this very similar to FIG. If you start with FIG and you decide you want to try Panamax or the other way around, it is really easy to go back and forth between the two tools. In addition to just having a UI, the other thing that Panamax has is support for remote deployment. So if you do get to a point where you're deploying this to a cluster running on Google Compute Engine, you can do that with the click of a button from Panamax. And if you want to download it, you can go to panamax.io, get Panamax. It is an open source project. It is all in Ruby. We are all Rubyists. So if you want to contribute, that would be super great. This is what an application template looks like with Panamax. So this is kind of an abbreviated version because there's a lot of other stuff that's maybe not so pertinent to this example. But we give it a name and a description. There's also support for things like documentation in there. And then you just start listing your images. So in this case, we have our Rails application with Postgres. And the first thing that we have is our Web Tier category, which is of course Rails. We have a source image. And then description of it, kind of type. The good stuff is down here in ports. All this configuration you just do once. And it stays with this template. You can, of course, change the template if you'd like to. But every time you run this template, the same exact things are going to happen over and over again. So why don't we look at Panamax. This is the homepage of Panamax. This is hooked directly to the Docker registry. We also have these fancy little buttons. So if you're interested in maybe running a Rails application, you can click on Rails in all of the pre-existing templates, which there are quite a few. There's probably 30 to 35 public templates that have been vetted by this lovely team of engineers that's sitting in the front row and myself to make sure that they do work. And from here you can just press run template. So you don't have to type anything. You can run locally. Or you can deploy it to your remote target, for example, like your Google Compute cluster or whatever kind of cluster you want to run. I'm just going to run it locally. And we'll see Panamax starting the application. And this may take a little bit and has to download the images. So everything that started with the Docker run string, it's just going on kind of in the background here. But great news, it was successfully created. And then I can see both of the services that I have here as well as my journal. So let's go in to download the image. And our familiar little friend, the Docker run string is over here. So what we really try to do with Panamax is make Docker easy, but not secret to use. And to that end, we do keep all of the artifacts around. We do show you the Docker run string. For example, if I wanted to add an environment variable in here, we can see the Docker run string auto update itself, just as I typed that. So when you use something with Panamax, you'll know exactly the equivalent of what you would be doing in real Docker on the CLI, except that you don't have to do it. You can just save it, make it a template, and then run it with a click of a button. I love application templating. It's kind of the game changer when you go from just tinkering with Docker to actually using it for maybe bootstrapping your development environment or managing all of your dependencies. If you have Postgres and Elasticsearch for every service or every application that you work on, just make a template with them and press like run. And then you have them, you don't have to kind of go through and set up all of your VMs or containers. And again, it's a Ruby open source Ruby project. You can find it on GitHub at CenturyLink Labs. And there's a few issues in the backlog if you want to work on it. Just saying. Okay. So that's it. We talked about what Docker is, what containers are, how to run them, how to run them with Ruby, how we might architect an application, and then finally how to template those applications to save yourself a lot of time. A few parting thoughts as you start on your containerized journey. Use Boot to Docker. It's really great. As you saw when I was packing away at Docker here, that was actually using Boot to Docker. I wasn't on my own machine. That was on a VM, but it sure didn't feel like it. Extract commonalities and put them in a base image. Anywhere you can use inheritance, please do it because it will save you so much time and resources because of that layer. Again, please don't put any passwords in your Docker file. And then use templating. It's a really fast way to get started. If you're looking for other resources or maybe you want to get started, some pretty good places to start, you want to look at the Docker club, see what's already out there and already exists. There's no use in reinventing the wheel. So you can use one of those official images, go for it. Docker has great documentation. Again, Boot to Docker. And then if you are interested in templating, you can look at Panamax or FIG at fig.sh. And then finally, the team of engineers I work with, we all write like pretty sometimes long form blog posts on different Docker images and sometimes do tutorials and you can find that at centurylinklabs.com. So thank you so much for being a great audience. And I hope you guys learned something about Docker. If anyone has any questions, I'll be happy to answer them or pretend like I know the answer.


We're stacking sales and I'm flippin' out! Who approved this? This month we're stacking deals on deals. 20% off already discounted items. Who did approve this? This is ridiculous. 1995, then it was 11.97. Now it's 20% really cheap. 20% off clearance items only applies to items on clearance and not any other discounts in store or online.


Yeah, thank you for the introduction and thanks a lot to the organizers to invite me. It was really funny to see my name in between all the famous people, so most of you probably won't know me. I'm Paul Cisca. Before I start my talk, I organized a guided snorkeling tour for tomorrow at two o'clock. It's 120 euros. We can be maximum 12 people. If you are interested in join, please send me an email with your name and telephone number and perhaps you could already now raise your hand if you want to join so that we can look forward it perhaps. Who wants to join? Okay. No, no, no, the entire group and they will provide snorkeling equipment and everything and it's Antonio told me it's a beautiful spot. It's around the corner. So yes, I'm looking forward to this and now my talk. So I'm dealing or I'm interested in how insects deal with these turbulent odor plumes. I think it's relevant also for mice because this is a normal way odorants distribute in the air. So animals, they encounter highly intermittent odorants and they encounter odor filaments or odor stimuli, which are very short and which rise from zero concentration to 100% of concentration within no time.  That means that you increase even more temporal intermittency and turbo lenses. I will talk about how insects, what kind of information insects can use to separate odorants from different sources. This behavioral data constrains the coding scheme. So it poses temporal constraints on how odor information can be encoded in the olfactory system and I will show you what are the physiological constraints of an odorant code by showing you the temporal precision of insect or factory receptor neurons. I like to, so I always show in fact this two odor plume picture from Antonio and Massimo's work which nicely shows how odorants from different sources intermingle or not intermingle. So what you see is that the thread and the screen odorants which are released from two nearby sources, they show correlated fluctuations but also uncorrelated fluctuations. They overlap to a certain degree but they also stay separated. So if you want to know whether this plume originates from one or from two sources, you have two different types of information available. One is you just sample the space and you know that here was the red odor and there was the green odor. That would help you to solve this odor segregation problem. Or you use temporal information. Their insects with their short antennae, in particular Osofila which have antennae which are I think 100 micrometer long, they don't have a spatial resolution. So they rely on temporal resolution and this is what I will tell you today. And Aya, please remember the introduction of Andreas Schäfer because he nicely explained this concept behind using temporal odorant structure to solve this object segregation task. And as Andreas, I also read this paper by Hopfeldt and I found it very inspiring. And so in particular the sentence. So I have to read it again. The variable nature of turbulent airflow makes such a remote sensing problem solvable if the animal can make use of the information conveyed by the fluctuations with time of the mixture of odor sources. Good. So if you are an insect with a small antenna with no spatial resolution, you need to have a good temporal resolution in order to do the source segregation. And here also comes the olfactory cocktail party or the cocktail party analogon in play. So when we want to solve this cocktail party problem, so when you start all talking at the same time now to me, I can use different mechanisms to separate your voices. So I can focus my attention to one voice. I hear from which directions the voices come, but there's additional information, and that is if you start talking, then all the sounds you produce, they will arrive in synchrony, they will fluctuate in synchrony, whereas when you are talking, your sounds, they will arrive with a different temporal signature. And in fact, our auditory system uses this information, so it can use odorant sounds and sound onset synchrony to segregate concurrent sounds. So here's one auditory example now. We have 24 sounds, they all start at the same time, you hear this. So you have heard one sound. Now we delay one of the frequencies, 600 thirds by 160 milliseconds. Now you hear this. Did you hear a difference? So you should have heard two sounds. I will play it again. Please listen. Or again. So is this a good analogy? Stimulus wise, I think it's a very good analogy, because you could think of the sounds as being odorants, all these which start synchronously come from one source, and this one odorant here comes from another source. But is it a good analogy for an olfactory segregation mechanism?  And so how do insects smell? The olfactory organs of insects, they are exposed to the air. So the receptor neurons, they are situated on the antennae in the senzilla. And they are continuously sampling the air. So it's not like sniffing. Insects continuously sample the odorant stimuli, and it is in fact a bit like as our hearing. We also continuously hear there is no intermittency due to sniffing or so. So in theory, insects have good access to the temporal structure of the stimulus. So when we want to investigate how insects perceive and process these temporal stimulus information, we need to precisely control the odorant stimuli. And this we do with an odorant delivery device which is capable to produce arbitrary binary mixtures where we can let fluctuate the odorants with frequencies up to 70 hertz. So these coherence plots show the temporal resolution of the odorant stimuli. And one important aspect is, or property, is that you can take different odorants which differ in volatility and differ in their stickiness to all the internal materials of an olfactory meter, which low pass to a different degree. These odorant stimuli, and if you apply these fluctuating odorants, so these traces show six different odorants, the temporal resolution is very similar. So this odor delivery device, I brought the heart of this. This is a polyether ketone body, which we equipped with fast-switching valves. And everybody can easily build this thing. So we supply in this paper, we provide all the plans to cut middle this. And it allows highly precise and from set up to set up highly reproducible odorant stimuli. Okay. So first we wanted to know whether insects can use odorant onset asynchrony to segregate odorants. And we did this experiment in honey bees. Because it's very easy to ask a honey bee whether she smells a certain odorant. And the logic or the experiment was as follows. We trained the honey bees to an odorant A to recognize this odorant. And then we tested the same honey bee with three mixtures of this odorant. So we mixed this odorant A with a novel odorant B. And we either presented this mixture as a synchronous mixture where the onset was simultaneously of these two odorants or we shifted the onset of the two odorants by just six milliseconds. And perhaps you see this little shift, so this is true to scale. The odorant stimulus is 800 milliseconds long. And this little shift in the onset is six milliseconds. And how do we ask a bee?  We do a classical conditioning. And this is shown here in this movie. So the odor is presented to the bee. Then we feature some sugar. And bees learn to respond to an odor within one trial. So very quickly, if you want to make them discriminate different odorants, you need just three trials. And then 60% or so of the bees would discriminate. And this is then the performance in the test after they learn that odor A is good. 50% of the bees responded to the synchronous mixture. And 70% roughly responded to these asynchronous mixtures. And one important finding was that it doesn't matter whether this mixture started with a rewarded odor A to which they responded or whether it started with a novel odorant. And so this data looks as if bees can use this asynchrony in the onset of the odorant to segregate these two odorants. Yes, please. Yeah. Yeah. Yeah. Exactly. So this F3B was stimulated with each of these three stimuli, one. So each bee received first three panic trials and then three test trials. But each bee got a different. I mean, the sequence was permeated as was the identity of the odorant. So this experiment was controlled with respect to the odorant and the sequence. And so bees show extinction. If you present these odorants over and over, they will learn that these odorants are not associated with sugar, but this extinction is rather slow. So it could be, but we don't see the learning. So this extinction learning, yeah, we don't see it in this data. Because we randomized the sequence, yeah, but if I would present one odor again and again, the response probability would go down to zero after a while. I didn't test it. So I used, this was like a preliminary experiment. This was the only, I did another experiment where I varied something else, but not the concentration. Yeah. So these concentrations are in the dynamic range of receptor-neuron activity. So it's diluted one to 1,000 in liquid and we know that we are not saturating the receptor neurons. Yeah. So we tested this in drosophila, how mixtures interact at the receptor level and also within one-cent-syllum, these different neurons which are housed in one-cent-syllum, how they interact with each other and we don't find a strong effect, but I can give you more details to this later. More questions? Okay. So then we proceeded, and now first I want to say that it's not only bees who can do it. So there are several invertebrate species which are capable to separate odorants either through spatial cues or temporal cues. All these animals, they have exposed olfactory organs, yeah, which are in direct contact with the air. What I found extremely exciting here that two days ago we learned from Tim Holy that even mice probably could solve this task because the spatial arrangement of odorants is mapped onto a spatial map in the nasal epithelium. So that probably would allow mice to use the spatial information to do an odor segregation. And we learned from Andreas Schäfer that mice are also sensitive for high-frequency temporal stimulus information. So I think these results are, I mean, at least for me, super exciting. I couldn't even get a better start on these ones. No, but I saw how sad you were when this disappeared, so I thought I saved it for your children. Okay, but now we want to know how much of this temporal information is actually available for the insect. So we recorded the temporal position of insect olfactory receptor neurons. Before I show you the data, I want to make a claim. I know first, so receptor neurons and insects, I have to introduce perhaps them quickly. So this is trosophila, and the following data which I will show you is all trosophila data. So trosophila, smell with their antennae, these are the antennae, they are covered with senzilla, and each senzillum houses two or three or four receptor neurons. The good thing is you can identify them all. It's very easy to find the same receptor neuron again and again. And this is the way how odor coding is normally quantified. You look at a population of receptor neurons, so this is worked by Marine de Bruyne. You give an odorant, and then you calculate the spike rate over a window of 500 milliseconds or any window. And then you see that each odorant activates a particular pattern of spike rates across those receptor neurons. These patterns allow us very well to identify any odorant. So one could think that these spike rate differences across receptor neurons encode the odorant identity. The disadvantage of such a rate code is that it takes a lot of time to be read out. So an odorant, two types of receptor neurons, odorant comes, receptor neurons change their rate. In order to read out the rate code, you have to integrate over at least two spikes. So the rate and also the precision with which these neurons produce these changes in spike rates then limits the temporal resolution of the odor code. But there are faster ways to encode information in the nervous system. You could just look or integrate over a small time window so that you, so me, I'm the post-anaptic neuron now and look which neuron populations fire in synchrony within a given time window. Such a synchrony code is limited by the jitter with which these receptor neurons generate their spikes. Another way to encode odorants is by looking at these relative patterns of first spike latencies and Andreas Schaefer modeled this and showed that this is a feasible coding scheme even for mice. Again, the temporal resolution of such a coding scheme is limited by the temporal position. So in fact, all coding schemes are limited by the temporal position of spike time generation. So what is the temporal position? That has never been directly measured in insects. One could think that insect receptor neurons are super fast because first they are exposed to this is one, one syncyllum of a drosophila. So you see these little holes, perhaps they are in direct contact with, with the air odorant molecules diffuse through these holes. They diffuse through the dendrites of the receptor neuron and then they directly open channels. So this is the transduction process in insects that could potentially be very fast. And so we wanted to know how fast is this process. So previous studies indicated that the minimum response latency of an insect receptor neuron is 10 milliseconds. Some other claim that it's 30 milliseconds, so not very fast. Okay, how did we address this question? So what is the speed of odor transduction and what is the temporal position of odor transduction? We did paired recordings from the same receptor neuron type in different syncylums by poking in tungsten electrodes into syncylums of the same type. Then you get these action potential traces. So you can identify receptor neurons based on the heights of their action potentials and then we presented a very fast odor pulse in order to mimic the situation that an insect is flying through a narrow odorant filament. So our odorant stimulus had a rise time of 3.6 milliseconds. So rise time from 5 to 95 percent of the signal of the stimulus. So this is the method. This is some data. So these raster plots show action potentials recorded in the one neuron and in the other neuron. So same receptor neuron type in one fly to 10 repeats of these odorant stimuli. Here we used the thielbutyrate at a concentration of 10 to the minus 5. So diluted in a solvent mineral oil, 10 to the minus 4, 10 to minus 3. A bar is 100 millisecond. So what you see is as you increase the concentration, these spikes, they tightly face lock or tightly lock to the stimulus. Okay. From this data, we first measured the response latency. So the time between arrival of the odorant and the generation of the first spike. On the x-axis, you see the concentrations. So we started with blank air and then represented the odorant concentrations, yeah, different odorant concentrations, so increasing concentrations. So these are lock orders of concentration. Note that the y-scale shows the response latency in milliseconds at the lock scale. So if you use very high concentrations, you get very short response latencies. So the median response latencies are depicted here. So 2.5 milliseconds, for example, at a high concentration of the thielbutyrate. If you record in these AB2A neurons, for example, these different points show the data from the single neuron types, neurons. Okay. This shows that odor transduction can be very, very fast. Then we wanted to know how precise is it. And in order to quantify the precision, we took the standard deviation of the first spike latencies. And we call this jitter. So this is also given in milliseconds. And again, these numbers here, they show the median jitter values over different animals, different neurons. And we find that as you increase the concentration, the jitter goes down to below a millisecond. So odor transduction is not only fast, it's also temporarily very precise. And this is, in fact, in the range of the jitter of mechanosensory or visual neurons. So it's not much slower or not much less precise than these temporarily very precise mechanical or even auditory receptor neurons. Yes. And not much. I will show this data for different odorants. It does not differ much. Could you speak up? Yes. I will show that we can use this. Now we want to compare it with the rate changes. In order to make it better comparable with these millisecond time scales, I plot here not the rate but the inverse rate, which means the interval between two consecutive spikes. And what we found is that, so first at highest concentration, we have the shortest interval between two spikes, three milliseconds, that corresponds to 330 spikes per second. And the interesting thing is that these changes in rate, they vary over a lower range of concentration. They vary over three orders of, lock orders of magnitude. Whereas the first spike latency or the jitter varies over at least one or two lock orders larger range. So you are more sensitive if you could use this timing information at the lower concentrations and you don't saturate as quickly at the higher concentrations. So there is more at least odorant concentration information contained in the precise spike timing than in the rates. And so to demonstrate that this precise spike timing is not an artifact of super high odorant concentration, I highlight here a concentration 10 to the minus 4 where we just see a significant response change or change in the rate. And we find a temporal position of 2.1 milliseconds already and a response latency of 10 milliseconds, which, yeah, which is short. It's the maximum spike rate. So we looked during the stimulus and took the maximum spike rate and here then depicted as the minimum inter-spike interval. But we find the same if we take just the interval between the first and the second spike, it gets really worse if we integrate over 100 milliseconds. So take the average rate, then we lose dynamic range massively, yeah. Yes, a little bit. I will show some data perhaps which will answer your question, yes? Population rates, but you mean across different neural populations? I will show it also, yeah, okay. So the cool thing, what you can do in Trozophila, which you cannot do in mice, is the following calculation. So we know exactly how the circuit is, the architecture of the circuit. So thanks to work from the Hansen's and Zilke's Access Lab, we know that there are exactly 23 of those AB2A neurons. So the data I showed you came from these neurons. We know also from their work is that they project onto one projection neuron in those glomerulus. And we know from Kazamas and Wilson's lab, Rachel Wilson's lab, that all receptor neurons may contact to this projection neuron or the other way around, perhaps each projection neuron in the Trozophila glomerulus gets input from all receptor neurons. So we know the conversion rate, which is here, 2321. This now allows us to estimate what is the minimum time window, a readout neuron, so projection neuron, which would be the analog to a midfield cell. What is the minimum time window of integration time needed to discriminate odor evoked spikes from spontaneously generated spikes? We did it by just counting the number of spikes across these 23 neurons in a given time window, let's say one millisecond. We get the distribution. So we have a perhaps mean number of spikes, let's say 70 spikes, and a standard deviation. And we do the same for a one millisecond time window before the stimulus. So we get also a mean spike number and distribution. And then in order to quantify the distance between or the separability between the odor evoked spikes and the spontaneously generated spikes, we just take the difference in these two means between the odorant and spontaneous spikes and normalize it by the standard deviation. So this is a common measure, which is called sensitivity index. Rachel Wilson used it to do exactly such a calculation. She called it detection accuracy. So it's a measure for how well you can separate two signals. These integration time windows, we were sliding over the time in order to see how does integration time or odorant information changes over time. We took the real data, we shuffled it, and we always picked like 23, but it's, yeah, so it's a real data-based simulation. So if we make this time window, for example, 32 milliseconds long, we count the number of spikes in 32 milliseconds and then measure the distance to the spontaneously evoked spikes in a 32 millisecond time window counted before the stimulus. Then we see that, so this is this magenta line that, like, after seven milliseconds or so, we cross a threshold of two, which would mean that our signal is like two times larger than the standard deviation of the noise, yeah, so we can express it like, simplified like this. And then it increases as you slide your window forward. The interesting thing is you can make your integration time windows very short, yeah, so if you look at the black trace, this is this signal detection accuracy if you have just a one millisecond time window. You also reach, within the same time, the threshold of two detection accuracy units. It does not go as high, but I mean I would think we don't need this high certainty as a read-out neuron that there was an odorant, probably two standard deviations above noises, probably enough. The interesting thing now is that in a time window of one millisecond, a maximum of one spikes fit per neuron, yeah, because neurons have a refractory period, so they need at least two milliseconds, let's say, to generate an X spike. So that means that a purely spike timing-based code, so if you just count the number of spikes in a very narrow time window after your odorant stimulus is enough to expect a lot of odorant information. Here we wanted to know what is the minimum time window now, the minimum integration time window or read-out neuron would need in order to cross this two standard deviation threshold. And we found ridiculously short integration time windows, so at the highest concentration you just need 10 microseconds to be certain that there was an odor, yeah. And even at concentrations, 10 to the minus 6, perhaps now I should switch to the next slide, so sorry it looks a bit different, but this is now the same stimulus detection concentration dependency what I just showed on the previous slide, so very short time windows are only needed for high concentrations. And now if we look at a concentration of 10 to the minus 6, where we don't see any signature of an odorant in the rate, if we just look at the rate, we see already that 4.4 milliseconds of integration time is enough to detect this odorant. And then with the next highest concentration you are already in a time window where only one neuron fits in, where you don't, where you can't have a, yeah, there's no need to read out the rates at any concentration actually, yes, yes, exactly, yeah. And I mean, I really like Dema's primacy code, I mean these Missile Booty rate for this is not the best ligand for this receptor neuron, yeah, so if you would take the best ligand, you would get even shorter times, yeah, and then if only six glomeruli would be sufficient to encode any given odorant, odorant detection identity, identification could happen in no time, yes, but I have to show you the circuit, I don't show it in the talk, but later I want to show it, I think it's possible, okay. So odorants are encoded in, yeah, in a combinatorial pattern, so and here I want to give an impression of the spatial or combinatorial pattern of activity if we take timing. So we recorded from two receptor neuron types, this is the AB2A neuron which I showed the data and the AB3A neuron, what I plotted here is, yeah, all the data we had actually for the first spike latencies for two different odorants, so the green is the Missile Booty rate which I just showed, magenta ethyl acetate and the different concentrations and you have to read this plot as follows, so if you look at this box, ethyl acetate at a concentration of 10 to the minus 3, this line here, the horizontal line shows the median first spike latency of the AB2A neuron, so it responds after around 6 milliseconds, yeah, and the boxes show the 5 to 95 percentile range. AB2A responds after 6 milliseconds, AB3A after perhaps 20 milliseconds, so what you see here is that if you like go from up to down, so from low concentration to high concentration, the response latencies become shorter, of course what you also see is that each odor evokes a specific sequence of response latencies, so the AB2A neuron always responds a little bit quicker to ethyl acetate as does the AB3A neuron and for Missile Booty rate it's the other way around, so odorant identity could be encoded in the order of receptor neuron activation, so whenever there's an odorant that first activates AB2A and then AB3A, it's more likely to be a fetal acetate than the tube Booty rate, so this is what this slide shows you, and the order is odorant specific, but it's invariant to concentration, so even though the latencies they vary over two orders of magnitude, the order stays stable, concentration invariant for different odorants, I don't know, I only tested these odorants here, so yeah, but he did calcium imaging, he has no spike data, so from this data I cannot estimate the response latencies, I think I didn't get your question fully, but you have to then also take into account all the other or many other receptor neurons, but first I have to do the experiment, so first I have to present all the other odorants and test with them, okay, so now let's compare this with an rate code performance, so again what is shown here is the minimum inter-spike interval, and one thing which stands out is that these patterns are highly correlated, so a neuron which fires with a high rate to one odorant also has short response latency, so there's a high correlation in these across neuron patterns, but what we see is that a rate code couldn't discriminate so well over a wide concentration range, yes, so this is just a slide which summarizes the work I did with Brian Smith and Rick Gurkin in Tempe where we tried to measure the response latency and the pulse tracking capability of insect antennae, so we shopped off insect antennae of different insect species and found that they could respond to highly concentrated odorants in this case within a few milliseconds, so this fits to the data we got from Trusophila, I didn't show you data showing how well spikes can follow repetitive pulses, but we found that Trusophila receptor neurons they can resolve up to 125 pulses per second as a population, and the same is true for these electroentronogram responses where we record from a huge population of receptor neurons, so in general odor transduction in insects is very fast and has a high temporal resolution, okay, so summary and conclusion, how much time do I have? Ah, super, okay, then time for discussion. Okay, so summary, so we found short first spike latencies of less than three milliseconds, we found that the jitter can be less than a millisecond, we found that stimulus detection could happen within less than 20 microseconds, we have to prove that projection neurons are sensitive actually that they can discriminate or have short integration time, so this will be my next project, so but I don't have data, I don't even have the setup for this yet, so what are the conclusions? First, which is trivial, synchrony across receptor neurons reliably encodes the onset of an odorant stimulus, so yeah when there is synchronous activity across receptor neurons the olfactory system should know that there was an odorant just right now or a few milliseconds before, we found that the latency and also the degree of synchrony or the jitter of the first spike latencies encodes odorant concentration, we found that the order of first spike latencies across receptor neurons encodes odorant identity and importantly is this concentration invariant and you are to conclude further, we think that the olfactory system could use temporal coding scheme for fluctuating odorant stimuli and because it is so highly correlated with these patterns of rates the olfactory system could actually use both, it could use a rate code for more static odorant stimuli and could switch between temporal or rate codes depending on the environment in which it just is and then what I at least find exciting is that the first spike latency code where the sequence or the order of receptor neuron activities encode odor identity is very well suited to do rapid odorant detection which would allow odorant source separation just because it's fast, yeah yes that's it, I want to acknowledge first of all Alfa Renner and Alex Egea Weiss two bachelor students and all these double recordings and data analysis were their bachelor thesis so they came into the lab completely untrained they got prosophala and set up and this is again a beauty of prosophala that you can do these experiments very easily together with Georg Reiser we developed this odor delivery device which I want to advertise Giovanni Galizia houses me so I'm an independent scientist but a little bit dependent because he provides me lab space and yeah he's a great colleague for discussion Christoph Klein-Eidem was also involved in these single-sensitum recordings and then yeah thanks to my HFSP grant team Thomas Novotny, Brian Smith and Riora Hekansaki we are trying to develop robots which can do odor background segregation which are equipped with moth antennae which are genetically modified so that they are responding to single odorants only and yeah thanks for your attention


Hey guys! I'm here today to talk about my favorite new dress, the Rosa Shirt Dress by Tilly and the Buttons, made out of an amazing lightweight denim blend from Hearts Fabric. I've had a denim shirt dress on my to-sew list for a while now, but just couldn't get my hands on the perfect denim. So many of the denims I found were either the wrong shade, had poor stretch recovery, had too much stretch, or were just plain poor quality. When Tilly released her Rosa Shirt Dress, my search for the perfect denim moved to the very top of my list, and my search led me to the Hearts Fabric website. I've always been obsessed with floral fabric, and when I came across this floral denim in the perfect shade of blue, I knew it had to be a Rosa. The fabric is on the lightweight side for a denim, making it the perfect choice for a shirt dress. The combination of cotton and polyester means that this fabric presses really beautifully and it doesn't wrinkle throughout a day of wear. It has a nice structure without being too stiff. It also has a slight amount of stretch, which makes it much more comfortable for a long day of wear. The roses have a white wash look to them, which gives them more of a vintage feel. I am extremely picky when it comes to the color of my denim, and I think this fabric is the perfect shade of blue that would flatter any skin tone. This fabric is manufactured by Helio, which is well known for their quality and affordability. I pre-washed my fabric on cold with wool light and tossed it in the dryer. It came out wrinkle-free and there was absolutely no fading in the color. It's sewed up as easily as a quilter's cotton, which makes it the perfect choice for a beginner seamstress. If you are thinking this large floral design is not quite your style, Hearts also carries two other designs with flowers that are much smaller. If flowers aren't your thing, then you might love the hearts, birds, or pineapples that it comes in. I'm just loving all these different designs available. If you are watching this and starting to feel a little jealous of my denim Rosa, but are also intimidated by the thought of making a shirt dress, then you can check out my pattern review over on my blog. I'll leave the link in the description box below. The Rosa shirt dress can be made out of pretty much any light to medium weight fabric. Hearts has this huge collection of these types of fabrics as well, but I have to say, after finishing my denim Rosa, I think you really need to give one of their denims a try. If I still haven't convinced you to give the Rosa pattern a try, then these denims would also work for a super cute skirt. I hope you enjoyed my review of this floral denim from Hearts fabric. Be sure to check out my blog for a review of the pattern and the video course that accompanies it. See you guys next time.